Browse Source

Configuration and deploy script for k8s on ACS

pull/190/head
Charles Lowell 8 years ago
parent
commit
a1f3a60ef9
7 changed files with 585 additions and 0 deletions
  1. +26
    -0
      k8s/README.md
  2. +80
    -0
      k8s/deploy.ps1
  3. +242
    -0
      k8s/deployments.yaml
  4. +47
    -0
      k8s/frontend.yaml
  5. +74
    -0
      k8s/nginx.conf
  6. +83
    -0
      k8s/services.yaml
  7. +33
    -0
      k8s/sql-data.yaml

+ 26
- 0
k8s/README.md View File

@ -0,0 +1,26 @@
# eShopOnContainers on Kubernetes
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`.
## Deploying the application
### Prerequisites
* A Docker build host.
* 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.
* 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.
### Run the deployment script
1. Open a PowerShell command line at `eShopOnContainers/k8s`.
1. Ensure `docker`, `docker-compose`, and `kubectl` are on the path, and configured for your Docker machine and Kubernetes cluster.
1. Run `deploy.ps1` with your registry information. For example:
```
./deploy.ps1 -registry myregistry.azurecr.io -dockerUser User -dockerPassword SecretPassword
```
The Docker username and password are provided by Azure Container Registry, and can be retrieved from the Azure portal.
The script will build the code and corresponding Docker images, push the latter to your registry, and deploy the application to your Kubernetes cluster.
TODOs
=====
* Host WebSPA at `/webspa`
* 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.
* Debug microservice resiliency issues--some microservices can enter failure states requiring their pod to be recreated.
* Respond to `kubectl` failures in `deploy.ps1`.

+ 80
- 0
k8s/deploy.ps1 View File

@ -0,0 +1,80 @@
Param(
[parameter(Mandatory=$true)][string]$registry,
[parameter(Mandatory=$true)][string]$dockerUser,
[parameter(Mandatory=$true)][string]$dockerPassword
)
$requiredCommands = ("docker", "docker-compose", "kubectl")
foreach ($command in $requiredCommands) {
if ((Get-Command $command -ErrorAction SilentlyContinue) -eq $null) {
Write-Host "$command must be on path" -ForegroundColor Red
exit
}
}
Write-Host "Logging in to $registry" -ForegroundColor Yellow
docker login -u $dockerUser -p $dockerPassword $registry
if (-not $LastExitCode -eq 0) {
Write-Host "Login failed" -ForegroundColor Red
exit
}
# create registry key secret
kubectl create secret docker-registry registry-key `
--docker-server=$registry `
--docker-username=$dockerUser `
--docker-password=$dockerPassword `
--docker-email=not@used.com
# start sql and frontend deployments
kubectl create configmap config-files --from-file=nginx-conf=nginx.conf
kubectl label configmap config-files app=eshop
kubectl create -f sql-data.yaml -f services.yaml -f frontend.yaml
Write-Host "Building solution..." -ForegroundColor Yellow
../cli-windows/build-bits-simple.ps1
Write-Host "Building Docker images..." -ForegroundColor Yellow
docker-compose -p .. -f ../docker-compose.yml build
Write-Host "Pushing images to $registry..." -ForegroundColor Yellow
$services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "webmvc", "webspa")
foreach ($service in $services) {
docker tag eshop/$service $registry/$service
docker push $registry/$service
}
Write-Host "Waiting for frontend's external ip..." -ForegroundColor Yellow
while ($true) {
$frontendUrl = kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}" 2> $_
if ([bool]($frontendUrl -as [ipaddress])) {
break
}
Start-Sleep -s 15
}
kubectl create configmap urls `
--from-literal=BasketUrl=http://$($frontendUrl)/basket-api `
--from-literal=CatalogUrl=http://$($frontendUrl)/catalog-api `
--from-literal=IdentityUrl=http://$($frontendUrl)/identity `
--from-literal=OrderingUrl=http://$($frontendUrl)/ordering-api `
--from-literal=MvcClient=http://$($frontendUrl)/webmvc `
--from-literal=SpaClient=http://$($frontendUrl)
kubectl label configmap urls app=eshop
# TODO verify database readiness?
Write-Host "Creating deployments..."
kubectl apply -f deployments.yaml
# update deployments with the private registry
# (deployment templating, or Helm, would obviate this)
kubectl set image -f deployments.yaml `
basket=$registry/basket.api `
catalog=$registry/catalog.api `
identity=$registry/identity.api `
ordering=$registry/ordering.api `
webmvc=$registry/webmvc `
webspa=$registry/webspa
kubectl rollout resume -f deployments.yaml
Write-Host "WebSPA is exposed at http://$frontendUrl, WebMVC at http://$frontendUrl/webmvc" -ForegroundColor Yellow

+ 242
- 0
k8s/deployments.yaml View File

@ -0,0 +1,242 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: basket
spec:
paused: true
template:
metadata:
labels:
app: eshop
component: basket
spec:
containers:
- name: basket
image: eshop/basket.api
imagePullPolicy: Always
env:
- name: ASPNETCORE_ENVIRONMENT
value: Development
- name: ASPNETCORE_URLS
value: http://0.0.0.0:80/basket-api
- name: ConnectionString
value: 127.0.0.1
- name: IdentityUrl
valueFrom:
configMapKeyRef:
name: urls
key: IdentityUrl
ports:
- containerPort: 80
- name: basket-data
image: redis
ports:
- containerPort: 6379
imagePullSecrets:
- name: registry-key
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: catalog
spec:
paused: true
template:
metadata:
labels:
app: eshop
component: catalog
spec:
containers:
- name: catalog
image: eshop/catalog.api
imagePullPolicy: Always
env:
- name: ASPNETCORE_ENVIRONMENT
value: Development
- name: ASPNETCORE_URLS
value: http://0.0.0.0:80/catalog-api
- name: ConnectionString
value: "Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word"
- name: ExternalCatalogBaseUrl
valueFrom:
configMapKeyRef:
name: urls
key: CatalogUrl
ports:
- containerPort: 80
imagePullSecrets:
- name: registry-key
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: identity
spec:
paused: true
template:
metadata:
labels:
app: eshop
component: identity
spec:
containers:
- name: identity
image: eshop/identity.api
imagePullPolicy: Always
env:
- name: ASPNETCORE_ENVIRONMENT
value: Development
- name: ASPNETCORE_URLS
value: http://0.0.0.0:80/identity
- name: ConnectionStrings__DefaultConnection
value: "Server=sql-data;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word"
- name: MvcClient
valueFrom:
configMapKeyRef:
name: urls
key: MvcClient
- name: SpaClient
valueFrom:
configMapKeyRef:
name: urls
key: SpaClient
ports:
- containerPort: 80
imagePullSecrets:
- name: registry-key
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: ordering
spec:
paused: true
template:
metadata:
labels:
app: eshop
component: ordering
spec:
containers:
- name: ordering
image: eshop/ordering.api
imagePullPolicy: Always
env:
- name: ASPNETCORE_ENVIRONMENT
value: Development
- name: ASPNETCORE_URLS
value: http://0.0.0.0:80/ordering-api
- name: ConnectionString
value: "Server=sql-data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;"
- name: IdentityUrl
valueFrom:
configMapKeyRef:
name: urls
key: IdentityUrl
ports:
- containerPort: 80
imagePullSecrets:
- name: registry-key
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: webmvc
spec:
paused: true
template:
metadata:
labels:
app: eshop
component: webmvc
spec:
containers:
- name: webmvc
image: eshop/webmvc
imagePullPolicy: Always
env:
- name: ASPNETCORE_ENVIRONMENT
value: Development
- name: ASPNETCORE_URLS
value: http://0.0.0.0:80/webmvc
- name: BasketUrl
valueFrom:
configMapKeyRef:
name: urls
key: BasketUrl
- name: CallBackUrl
valueFrom:
configMapKeyRef:
name: urls
key: MvcClient
- name: CatalogUrl
valueFrom:
configMapKeyRef:
name: urls
key: CatalogUrl
- name: IdentityUrl
valueFrom:
configMapKeyRef:
name: urls
key: IdentityUrl
- name: OrderingUrl
valueFrom:
configMapKeyRef:
name: urls
key: OrderingUrl
ports:
- containerPort: 80
imagePullSecrets:
- name: registry-key
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: webspa
spec:
paused: true
template:
metadata:
labels:
app: eshop
component: webspa
spec:
containers:
- name: webspa
image: eshop/webspa
imagePullPolicy: Always
env:
- name: ASPNETCORE_ENVIRONMENT
value: Development
- name: ASPNETCORE_URLS
value: http://0.0.0.0:80
- name: BasketUrl
valueFrom:
configMapKeyRef:
name: urls
key: BasketUrl
- name: CallBackUrl
valueFrom:
configMapKeyRef:
name: urls
key: SpaClient
- name: CatalogUrl
valueFrom:
configMapKeyRef:
name: urls
key: CatalogUrl
- name: IdentityUrl
valueFrom:
configMapKeyRef:
name: urls
key: IdentityUrl
- name: OrderingUrl
valueFrom:
configMapKeyRef:
name: urls
key: OrderingUrl
ports:
- containerPort: 80
imagePullSecrets:
- name: registry-key

+ 47
- 0
k8s/frontend.yaml View File

@ -0,0 +1,47 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: eshop
component: frontend
name: frontend
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: eshop
component: frontend
type: LoadBalancer
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend
spec:
template:
metadata:
labels:
app: eshop
component: frontend
spec:
containers:
- name: nginx
image: nginx:1.11.10-alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
lifecycle:
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
volumeMounts:
- name: config
mountPath: /etc/nginx
volumes:
- name: config
configMap:
name: config-files
items:
- key: nginx-conf
path: nginx.conf

+ 74
- 0
k8s/nginx.conf View File

@ -0,0 +1,74 @@
pid /tmp/nginx.pid;
worker_processes 1;
events {
worker_connections 1024;
}
http {
server_tokens off;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
client_body_temp_path /tmp/client_body;
fastcgi_temp_path /tmp/fastcgi_temp;
proxy_temp_path /tmp/proxy_temp;
scgi_temp_path /tmp/scgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
gzip on;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_buffers 4 32k;
gzip_types text/plain application/javascript text/css;
gzip_vary on;
keepalive_timeout 65;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
server {
listen 8080;
location /basket-api {
proxy_pass http://basket;
proxy_redirect off;
proxy_set_header Host $host;
}
location /catalog-api {
proxy_pass http://catalog;
proxy_redirect off;
proxy_set_header Host $host;
}
location /identity {
proxy_pass http://identity;
proxy_redirect off;
proxy_set_header Host $host;
}
location /ordering-api {
proxy_pass http://ordering;
proxy_redirect off;
proxy_set_header Host $host;
}
location /webmvc {
proxy_pass http://webmvc;
proxy_redirect off;
proxy_set_header Host $host;
}
location / {
proxy_pass http://webspa;
proxy_redirect off;
proxy_set_header Host $host;
}
}
}

+ 83
- 0
k8s/services.yaml View File

@ -0,0 +1,83 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: eshop
component: basket
name: basket
spec:
ports:
- port: 80
selector:
app: eshop
component: basket
---
apiVersion: v1
kind: Service
metadata:
labels:
app: eshop
component: catalog
name: catalog
spec:
ports:
- port: 80
selector:
app: eshop
component: catalog
---
apiVersion: v1
kind: Service
metadata:
labels:
app: eshop
component: identity
name: identity
spec:
ports:
- port: 80
selector:
app: eshop
component: identity
---
apiVersion: v1
kind: Service
metadata:
labels:
app: eshop
component: ordering
name: ordering
spec:
ports:
- port: 80
selector:
app: eshop
component: ordering
---
apiVersion: v1
kind: Service
metadata:
labels:
app: eshop
component: webmvc
name: webmvc
spec:
ports:
- port: 80
selector:
app: eshop
component: webmvc
---
apiVersion: v1
kind: Service
metadata:
labels:
app: eshop
component: webspa
name: webspa
spec:
ports:
- port: 80
selector:
app: eshop
component: webspa

+ 33
- 0
k8s/sql-data.yaml View File

@ -0,0 +1,33 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: eshop
component: sql-data
name: sql-data
spec:
ports:
- port: 1433
selector:
app: eshop
component: sql-data
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: sql-data
spec:
template:
metadata:
labels:
app: eshop
component: sql-data
spec:
containers:
- name: sql-data
image: microsoft/mssql-server-linux:ctp1-3
env:
- name: ACCEPT_EULA
value: "Y"
- name: SA_PASSWORD
value: Pass@word

Loading…
Cancel
Save