Skip to content

Commit a1f3a60

Browse files
committed
Configuration and deploy script for k8s on ACS
1 parent 4dc56c4 commit a1f3a60

7 files changed

Lines changed: 585 additions & 0 deletions

File tree

k8s/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# eShopOnContainers on Kubernetes
2+
This directory contains Kubernetes configuration for the eShopOnContainers app and a PowerShell script to deploy it to a cluster. Each microservice has a deployment configuration in `deployments.yaml`, and is exposed to the cluster by a service in `services.yaml`. The microservices are exposed externally on individual routes (`/basket-api`, `/webmvc`, etc.) by an nginx reverse proxy as specified in `frontend.yaml` and `nginx.conf`.
3+
4+
## Deploying the application
5+
### Prerequisites
6+
* A Docker build host.
7+
* A private Docker registry. Follow Azure Container Registry's [guide](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-portal) to create one.
8+
* A Kubernetes cluster. Follow Azure Container Service's [walkthrough](https://docs.microsoft.com/en-us/azure/container-service/container-service-kubernetes-walkthrough) to create one.
9+
10+
### Run the deployment script
11+
1. Open a PowerShell command line at `eShopOnContainers/k8s`.
12+
1. Ensure `docker`, `docker-compose`, and `kubectl` are on the path, and configured for your Docker machine and Kubernetes cluster.
13+
1. Run `deploy.ps1` with your registry information. For example:
14+
```
15+
./deploy.ps1 -registry myregistry.azurecr.io -dockerUser User -dockerPassword SecretPassword
16+
```
17+
The Docker username and password are provided by Azure Container Registry, and can be retrieved from the Azure portal.
18+
19+
The script will build the code and corresponding Docker images, push the latter to your registry, and deploy the application to your Kubernetes cluster.
20+
21+
TODOs
22+
=====
23+
* Host WebSPA at `/webspa`
24+
* This is blocked on correct relative URLs for images. Presently these are set at build by webpack, which isn't aware of where the app will be sited. An Angular solution might exist. Another option is to encode the images in base64.
25+
* Debug microservice resiliency issues--some microservices can enter failure states requiring their pod to be recreated.
26+
* Respond to `kubectl` failures in `deploy.ps1`.

k8s/deploy.ps1

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
Param(
2+
[parameter(Mandatory=$true)][string]$registry,
3+
[parameter(Mandatory=$true)][string]$dockerUser,
4+
[parameter(Mandatory=$true)][string]$dockerPassword
5+
)
6+
7+
$requiredCommands = ("docker", "docker-compose", "kubectl")
8+
foreach ($command in $requiredCommands) {
9+
if ((Get-Command $command -ErrorAction SilentlyContinue) -eq $null) {
10+
Write-Host "$command must be on path" -ForegroundColor Red
11+
exit
12+
}
13+
}
14+
15+
Write-Host "Logging in to $registry" -ForegroundColor Yellow
16+
docker login -u $dockerUser -p $dockerPassword $registry
17+
if (-not $LastExitCode -eq 0) {
18+
Write-Host "Login failed" -ForegroundColor Red
19+
exit
20+
}
21+
22+
# create registry key secret
23+
kubectl create secret docker-registry registry-key `
24+
--docker-server=$registry `
25+
--docker-username=$dockerUser `
26+
--docker-password=$dockerPassword `
27+
--docker-email=not@used.com
28+
29+
# start sql and frontend deployments
30+
kubectl create configmap config-files --from-file=nginx-conf=nginx.conf
31+
kubectl label configmap config-files app=eshop
32+
kubectl create -f sql-data.yaml -f services.yaml -f frontend.yaml
33+
34+
Write-Host "Building solution..." -ForegroundColor Yellow
35+
../cli-windows/build-bits-simple.ps1
36+
37+
Write-Host "Building Docker images..." -ForegroundColor Yellow
38+
docker-compose -p .. -f ../docker-compose.yml build
39+
40+
Write-Host "Pushing images to $registry..." -ForegroundColor Yellow
41+
$services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "webmvc", "webspa")
42+
foreach ($service in $services) {
43+
docker tag eshop/$service $registry/$service
44+
docker push $registry/$service
45+
}
46+
47+
Write-Host "Waiting for frontend's external ip..." -ForegroundColor Yellow
48+
while ($true) {
49+
$frontendUrl = kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}" 2> $_
50+
if ([bool]($frontendUrl -as [ipaddress])) {
51+
break
52+
}
53+
Start-Sleep -s 15
54+
}
55+
56+
kubectl create configmap urls `
57+
--from-literal=BasketUrl=http://$($frontendUrl)/basket-api `
58+
--from-literal=CatalogUrl=http://$($frontendUrl)/catalog-api `
59+
--from-literal=IdentityUrl=http://$($frontendUrl)/identity `
60+
--from-literal=OrderingUrl=http://$($frontendUrl)/ordering-api `
61+
--from-literal=MvcClient=http://$($frontendUrl)/webmvc `
62+
--from-literal=SpaClient=http://$($frontendUrl)
63+
kubectl label configmap urls app=eshop
64+
65+
# TODO verify database readiness?
66+
Write-Host "Creating deployments..."
67+
kubectl apply -f deployments.yaml
68+
69+
# update deployments with the private registry
70+
# (deployment templating, or Helm, would obviate this)
71+
kubectl set image -f deployments.yaml `
72+
basket=$registry/basket.api `
73+
catalog=$registry/catalog.api `
74+
identity=$registry/identity.api `
75+
ordering=$registry/ordering.api `
76+
webmvc=$registry/webmvc `
77+
webspa=$registry/webspa
78+
kubectl rollout resume -f deployments.yaml
79+
80+
Write-Host "WebSPA is exposed at http://$frontendUrl, WebMVC at http://$frontendUrl/webmvc" -ForegroundColor Yellow

k8s/deployments.yaml

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
apiVersion: extensions/v1beta1
2+
kind: Deployment
3+
metadata:
4+
name: basket
5+
spec:
6+
paused: true
7+
template:
8+
metadata:
9+
labels:
10+
app: eshop
11+
component: basket
12+
spec:
13+
containers:
14+
- name: basket
15+
image: eshop/basket.api
16+
imagePullPolicy: Always
17+
env:
18+
- name: ASPNETCORE_ENVIRONMENT
19+
value: Development
20+
- name: ASPNETCORE_URLS
21+
value: http://0.0.0.0:80/basket-api
22+
- name: ConnectionString
23+
value: 127.0.0.1
24+
- name: IdentityUrl
25+
valueFrom:
26+
configMapKeyRef:
27+
name: urls
28+
key: IdentityUrl
29+
ports:
30+
- containerPort: 80
31+
- name: basket-data
32+
image: redis
33+
ports:
34+
- containerPort: 6379
35+
imagePullSecrets:
36+
- name: registry-key
37+
---
38+
apiVersion: extensions/v1beta1
39+
kind: Deployment
40+
metadata:
41+
name: catalog
42+
spec:
43+
paused: true
44+
template:
45+
metadata:
46+
labels:
47+
app: eshop
48+
component: catalog
49+
spec:
50+
containers:
51+
- name: catalog
52+
image: eshop/catalog.api
53+
imagePullPolicy: Always
54+
env:
55+
- name: ASPNETCORE_ENVIRONMENT
56+
value: Development
57+
- name: ASPNETCORE_URLS
58+
value: http://0.0.0.0:80/catalog-api
59+
- name: ConnectionString
60+
value: "Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word"
61+
- name: ExternalCatalogBaseUrl
62+
valueFrom:
63+
configMapKeyRef:
64+
name: urls
65+
key: CatalogUrl
66+
ports:
67+
- containerPort: 80
68+
imagePullSecrets:
69+
- name: registry-key
70+
---
71+
apiVersion: extensions/v1beta1
72+
kind: Deployment
73+
metadata:
74+
name: identity
75+
spec:
76+
paused: true
77+
template:
78+
metadata:
79+
labels:
80+
app: eshop
81+
component: identity
82+
spec:
83+
containers:
84+
- name: identity
85+
image: eshop/identity.api
86+
imagePullPolicy: Always
87+
env:
88+
- name: ASPNETCORE_ENVIRONMENT
89+
value: Development
90+
- name: ASPNETCORE_URLS
91+
value: http://0.0.0.0:80/identity
92+
- name: ConnectionStrings__DefaultConnection
93+
value: "Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word"
94+
- name: MvcClient
95+
valueFrom:
96+
configMapKeyRef:
97+
name: urls
98+
key: MvcClient
99+
- name: SpaClient
100+
valueFrom:
101+
configMapKeyRef:
102+
name: urls
103+
key: SpaClient
104+
ports:
105+
- containerPort: 80
106+
imagePullSecrets:
107+
- name: registry-key
108+
---
109+
apiVersion: extensions/v1beta1
110+
kind: Deployment
111+
metadata:
112+
name: ordering
113+
spec:
114+
paused: true
115+
template:
116+
metadata:
117+
labels:
118+
app: eshop
119+
component: ordering
120+
spec:
121+
containers:
122+
- name: ordering
123+
image: eshop/ordering.api
124+
imagePullPolicy: Always
125+
env:
126+
- name: ASPNETCORE_ENVIRONMENT
127+
value: Development
128+
- name: ASPNETCORE_URLS
129+
value: http://0.0.0.0:80/ordering-api
130+
- name: ConnectionString
131+
value: "Server=sql-data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;"
132+
- name: IdentityUrl
133+
valueFrom:
134+
configMapKeyRef:
135+
name: urls
136+
key: IdentityUrl
137+
ports:
138+
- containerPort: 80
139+
imagePullSecrets:
140+
- name: registry-key
141+
---
142+
apiVersion: extensions/v1beta1
143+
kind: Deployment
144+
metadata:
145+
name: webmvc
146+
spec:
147+
paused: true
148+
template:
149+
metadata:
150+
labels:
151+
app: eshop
152+
component: webmvc
153+
spec:
154+
containers:
155+
- name: webmvc
156+
image: eshop/webmvc
157+
imagePullPolicy: Always
158+
env:
159+
- name: ASPNETCORE_ENVIRONMENT
160+
value: Development
161+
- name: ASPNETCORE_URLS
162+
value: http://0.0.0.0:80/webmvc
163+
- name: BasketUrl
164+
valueFrom:
165+
configMapKeyRef:
166+
name: urls
167+
key: BasketUrl
168+
- name: CallBackUrl
169+
valueFrom:
170+
configMapKeyRef:
171+
name: urls
172+
key: MvcClient
173+
- name: CatalogUrl
174+
valueFrom:
175+
configMapKeyRef:
176+
name: urls
177+
key: CatalogUrl
178+
- name: IdentityUrl
179+
valueFrom:
180+
configMapKeyRef:
181+
name: urls
182+
key: IdentityUrl
183+
- name: OrderingUrl
184+
valueFrom:
185+
configMapKeyRef:
186+
name: urls
187+
key: OrderingUrl
188+
ports:
189+
- containerPort: 80
190+
imagePullSecrets:
191+
- name: registry-key
192+
---
193+
apiVersion: extensions/v1beta1
194+
kind: Deployment
195+
metadata:
196+
name: webspa
197+
spec:
198+
paused: true
199+
template:
200+
metadata:
201+
labels:
202+
app: eshop
203+
component: webspa
204+
spec:
205+
containers:
206+
- name: webspa
207+
image: eshop/webspa
208+
imagePullPolicy: Always
209+
env:
210+
- name: ASPNETCORE_ENVIRONMENT
211+
value: Development
212+
- name: ASPNETCORE_URLS
213+
value: http://0.0.0.0:80
214+
- name: BasketUrl
215+
valueFrom:
216+
configMapKeyRef:
217+
name: urls
218+
key: BasketUrl
219+
- name: CallBackUrl
220+
valueFrom:
221+
configMapKeyRef:
222+
name: urls
223+
key: SpaClient
224+
- name: CatalogUrl
225+
valueFrom:
226+
configMapKeyRef:
227+
name: urls
228+
key: CatalogUrl
229+
- name: IdentityUrl
230+
valueFrom:
231+
configMapKeyRef:
232+
name: urls
233+
key: IdentityUrl
234+
- name: OrderingUrl
235+
valueFrom:
236+
configMapKeyRef:
237+
name: urls
238+
key: OrderingUrl
239+
ports:
240+
- containerPort: 80
241+
imagePullSecrets:
242+
- name: registry-key

k8s/frontend.yaml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
labels:
5+
app: eshop
6+
component: frontend
7+
name: frontend
8+
spec:
9+
ports:
10+
- port: 80
11+
targetPort: 8080
12+
selector:
13+
app: eshop
14+
component: frontend
15+
type: LoadBalancer
16+
---
17+
apiVersion: extensions/v1beta1
18+
kind: Deployment
19+
metadata:
20+
name: frontend
21+
spec:
22+
template:
23+
metadata:
24+
labels:
25+
app: eshop
26+
component: frontend
27+
spec:
28+
containers:
29+
- name: nginx
30+
image: nginx:1.11.10-alpine
31+
imagePullPolicy: IfNotPresent
32+
ports:
33+
- containerPort: 8080
34+
lifecycle:
35+
preStop:
36+
exec:
37+
command: ["/usr/sbin/nginx","-s","quit"]
38+
volumeMounts:
39+
- name: config
40+
mountPath: /etc/nginx
41+
volumes:
42+
- name: config
43+
configMap:
44+
name: config-files
45+
items:
46+
- key: nginx-conf
47+
path: nginx.conf

0 commit comments

Comments
 (0)