Skip to content

Commit e3f4388

Browse files
committed
Modify k8s deployment script to support CD/CI deployment
Create documentation
1 parent 9cff047 commit e3f4388

6 files changed

Lines changed: 131 additions & 46 deletions

File tree

README.CICD.k8s.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Kubernetes CI/CD VSTS
2+
For k8s CI/CD pipeline delivery a series of tasks must be created in VSTS to deploy k8s in Azure
3+
4+
## Prerequisites
5+
* 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.
6+
* 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.
7+
* Optionally, previous steps can be skipped if you run gen-k8s-env.ps1 script to automatically create the azure environment needed for kubernetes deployment. Azure cli 2.0 must be previously installed [installation guide](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli). For example:
8+
>```
9+
>./gen-k8s-env -resourceGroupName k8sGroup -location westeurope -registryName k8sregistry -orchestratorName k8s-cluster -dnsName k8s-dns
10+
>```
11+
* An `Azure Blob storage`. It is needed for storing the kubernetes config file used by the hosted agent to access to Kubernetes cluster. Example:
12+
13+
<img src="img/k8s/blob_creation.png">
14+
15+
* Upload the `kubernetes config file` to the blob storage previously created. Execute the following command which will download the config file into the directory `c:\Users\<User>\.kube\` and then, upload it to your blob storage:
16+
>```
17+
>https://eshopk8s.blob.core.windows.net/k8s-config/config
18+
>```
19+
## Create the VSTS tasks
20+
1. Create a `Download File` task to download the kubernetes binary `kubectl` to the hosted agent. For example:
21+
>```
22+
>https://storage.googleapis.com/kubernetes-release/release/v0.0.1.7.0-alpha.0/bin/windows/386/kubectl.exe
23+
>```
24+
<img src="img/k8s/get_kubectlbin_task.png">
25+
26+
2. Create a Download File task to download the kubernetes config file to the hosted agent. For example:
27+
>```
28+
>https://eshopk8s.blob.core.windows.net/k8s-config/config
29+
>```
30+
<img src="img/k8s/get_kubectlconfig_task.png">
31+
32+
3. Create a powershell task to execute the k8s deployment script. For example:
33+
34+
* Deployment script path
35+
>```
36+
>$(System.DefaultWorkingDirectory)/All Microservices/docker-compose/deploy.ps1
37+
>```
38+
39+
* Deployment script path arguments. Where:
40+
- userDockerHub: indicates if Docker Hub is used instead of ACR
41+
- deployCI: indicates that it is a CI/CD deployment
42+
- execPath: path where the k8s binary is stored
43+
- kubeconfigPath: path where the k8s config file is stored
44+
>```
45+
>-deployCI $true -useDockerHub $true -execPath '$(System.DefaultWorkingDirectory)/' -kubeconfigPath '$(System.DefaultWorkingDirectory)/'
46+
>```
47+
48+
<img src="img/k8s/deploy_script_task.png">

img/k8s/blob_creation.png

25.7 KB
Loading

img/k8s/deploy_script_task.png

36.3 KB
Loading

img/k8s/get_kubectlbin_task.png

31.4 KB
Loading

img/k8s/get_kubectlconfig_task.png

30.5 KB
Loading

k8s/deploy.ps1

Lines changed: 83 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,117 @@
11
Param(
2-
[parameter(Mandatory=$true)][string]$registry,
3-
[parameter(Mandatory=$true)][string]$dockerUser,
4-
[parameter(Mandatory=$true)][string]$dockerPassword
2+
[parameter(Mandatory=$false)][string]$registry,
3+
[parameter(Mandatory=$false)][string]$dockerUser,
4+
[parameter(Mandatory=$false)][string]$dockerPassword,
5+
[parameter(Mandatory=$false)][bool]$deployCI,
6+
[parameter(Mandatory=$false)][bool]$useDockerHub,
7+
[parameter(Mandatory=$false)][string]$execPath,
8+
[parameter(Mandatory=$false)][string]$kubeconfigPath
59
)
610

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
11+
function ExecKube($cmd) {
12+
if($deployCI) {
13+
$kubeconfig = $kubeconfigPath + 'config';
14+
$exp = $execPath + 'kubectl ' + $cmd + ' --kubeconfig=' + $kubeconfig
15+
Invoke-Expression $exp
16+
}
17+
else{
18+
$exp = $execPath + 'kubectl ' + $cmd
19+
Invoke-Expression $exp
1220
}
1321
}
1422

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
23+
# Not used when deploying through CI VSTS
24+
if(-not $deployCI) {
25+
$requiredCommands = ("docker", "docker-compose", "kubectl")
26+
foreach ($command in $requiredCommands) {
27+
if ((Get-Command $command -ErrorAction SilentlyContinue) -eq $null) {
28+
Write-Host "$command must be on path" -ForegroundColor Red
29+
exit
30+
}
31+
}
2032
}
2133

22-
# create registry key secret
23-
kubectl create secret docker-registry registry-key `
34+
# Use ACR instead of DockerHub as image repository
35+
if(-not $useDockerHub) {
36+
Write-Host "Logging in to $registry" -ForegroundColor Yellow
37+
docker login -u $dockerUser -p $dockerPassword $registry
38+
if (-not $LastExitCode -eq 0) {
39+
Write-Host "Login failed" -ForegroundColor Red
40+
exit
41+
}
42+
43+
# create registry key secret
44+
ExecKube -cmd 'create secret docker-registry registry-key `
2445
--docker-server=$registry `
2546
--docker-username=$dockerUser `
2647
--docker-password=$dockerPassword `
27-
--docker-email=not@used.com
48+
--docker-email=not@used.com'
49+
}
2850

29-
# start sql, rabbitmq, 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 rabbitmq.yaml -f services.yaml -f frontend.yaml
51+
# Removing previous services & deployments
52+
Write-Host "Removing existing services & deployments.." -ForegroundColor Yellow
53+
ExecKube -cmd 'delete -f sql-data.yaml -f rabbitmq.yaml'
54+
ExecKube -cmd 'delete -f services.yaml -f frontend.yaml -f deployments.yaml'
55+
ExecKube -cmd 'delete configmap config-files'
56+
ExecKube -cmd 'delete configmap urls'
3357

34-
Write-Host "Building and publishing eShopOnContainers..." -ForegroundColor Yellow
35-
dotnet restore ../eShopOnContainers-ServicesAndWebApps.sln
36-
dotnet publish -c Release -o obj/Docker/publish ../eShopOnContainers-ServicesAndWebApps.sln
58+
# start sql, rabbitmq, frontend deploymentsExecKube -cmd 'delete configmap config-files'
59+
ExecKube -cmd 'create configmap config-files --from-file=nginx-conf=nginx.conf'
60+
ExecKube -cmd 'label configmap config-files app=eshop'
61+
ExecKube -cmd 'create -f sql-data.yaml -f rabbitmq.yaml -f services.yaml -f frontend.yaml'
3762

38-
Write-Host "Building Docker images..." -ForegroundColor Yellow
39-
docker-compose -p .. -f ../docker-compose.yml build
63+
# building and publishing docker images not necessary when deploying through CI VSTS
64+
if(-not $deployCI) {
65+
Write-Host "Building and publishing eShopOnContainers..." -ForegroundColor Yellow
66+
dotnet restore ../eShopOnContainers-ServicesAndWebApps.sln
67+
dotnet publish -c Release -o obj/Docker/publish ../eShopOnContainers-ServicesAndWebApps.sln
4068

41-
Write-Host "Pushing images to $registry..." -ForegroundColor Yellow
42-
$services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "webmvc", "webspa")
43-
foreach ($service in $services) {
44-
docker tag eshop/$service $registry/eshop/$service
45-
docker push $registry/eshop/$service
69+
Write-Host "Building Docker images..." -ForegroundColor Yellow
70+
docker-compose -p .. -f ../docker-compose.yml build
71+
72+
Write-Host "Pushing images to $registry..." -ForegroundColor Yellow
73+
$services = ("basket.api", "catalog.api", "identity.api", "ordering.api", "webmvc", "webspa")
74+
foreach ($service in $services) {
75+
docker tag eshop/$service $registry/eshop/$service
76+
docker push $registry/eshop/$service
77+
}
4678
}
4779

4880
Write-Host "Waiting for frontend's external ip..." -ForegroundColor Yellow
4981
while ($true) {
50-
$frontendUrl = kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"
82+
$frontendUrl = & ExecKube -cmd 'get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"'
5183
if ([bool]($frontendUrl -as [ipaddress])) {
5284
break
5385
}
5486
Start-Sleep -s 15
5587
}
5688

57-
kubectl create configmap urls `
89+
ExecKube -cmd 'create configmap urls `
5890
--from-literal=BasketUrl=http://$($frontendUrl)/basket-api `
5991
--from-literal=CatalogUrl=http://$($frontendUrl)/catalog-api `
6092
--from-literal=IdentityUrl=http://$($frontendUrl)/identity `
6193
--from-literal=OrderingUrl=http://$($frontendUrl)/ordering-api `
6294
--from-literal=MvcClient=http://$($frontendUrl)/webmvc `
63-
--from-literal=SpaClient=http://$($frontendUrl)
64-
kubectl label configmap urls app=eshop
95+
--from-literal=SpaClient=http://$($frontendUrl)'
96+
97+
ExecKube -cmd 'label configmap urls app=eshop'
6598

6699
Write-Host "Creating deployments..."
67-
kubectl apply -f deployments.yaml
68-
69-
# update deployments with the private registry before k8s tries to pull images
70-
# (deployment templating, or Helm, would obviate this)
71-
kubectl set image -f deployments.yaml `
72-
basket=$registry/eshop/basket.api `
73-
catalog=$registry/eshop/catalog.api `
74-
identity=$registry/eshop/identity.api `
75-
ordering=$registry/eshop/ordering.api `
76-
webmvc=$registry/eshop/webmvc `
77-
webspa=$registry/eshop/webspa
78-
kubectl rollout resume -f deployments.yaml
100+
ExecKube -cmd 'create -f deployments.yaml'
101+
102+
# not using ACR for pulling images when deploying through CI VSTS
103+
if(-not $deployCI) {
104+
# update deployments with the private registry before k8s tries to pull images
105+
# (deployment templating, or Helm, would obviate this)
106+
ExecKube -cmd 'set image -f deployments.yaml `
107+
basket=$registry/eshop/basket.api `
108+
catalog=$registry/eshop/catalog.api `
109+
identity=$registry/eshop/identity.api `
110+
ordering=$registry/eshop/ordering.api `
111+
webmvc=$registry/eshop/webmvc `
112+
webspa=$registry/eshop/webspa'
113+
}
114+
115+
ExecKube -cmd 'rollout resume -f deployments.yaml'
79116

80117
Write-Host "WebSPA is exposed at http://$frontendUrl, WebMVC at http://$frontendUrl/webmvc" -ForegroundColor Yellow

0 commit comments

Comments
 (0)