In this lab we will create a tiny, single node kubernetes cluster, and deploy our code to it. In the following, we’ll use K8s (Kubernetes) or AKS (Azure Kubernetes Service) to shorten things…
kubernetes
in the search field, then select
Kubernetes Service
from the list.B2s
.
###Background
Unlike a VM where you can ssh
into and run bash scripts and all this, kubernetes is steered via an API server (the Kubernetes
master node). Almost the only tool you will ever need is kubectl
to manage deployments and configuration. And - almost
all of these actions are driven by sending a specifically tailored .yml
(or .yaml
) file with the help of kubectl
.
minikube start
and wait for it to com up.minikube kubectl get ns
. The output should be similar to this:
$ minikube kubectl get ns 💾 Downloading kubectl v1.15.2 NAME STATUS AGE default Active 95s kube-node-lease Active 98s kube-public Active 98s kube-system Active 98s
manifests
and create preliminary deployment.yaml in that directory with the following content:
apiVersion: apps/v1 kind: Deployment metadata: name: demoapp labels: app: demoapp spec: replicas: 1 selector: matchLabels: app: demoapp template: metadata: labels: app: demoapp spec: containers: - name: demoapp imagePullPolicy: IfNotPresent image: nemoregistrysandbox.azurecr.io/demoapp ports: - containerPort: 8080
NOTE: Minikube is running in a virtual machine (at least on MacOS and Windows) and therefore it’s isolated
from the host operating system(yes, your laptop) for security reasons. Our deployment.yml file references an image
named demoapp
, which indicates, that it should look in a local registry. The local registry for minikube unfortunately
is the one within the VM. So now we will turn things around and expose the VM’s docker registry to our laptop.
To do so, run
$ eval $(minikube docker-env)
to set your environment to point to minikube’s docker registry and re-run the build:
$ docker build -t demoapp --build-arg JAR_FILE=build/libs/demo-0.0.1-SNAPSHOT.jar .
port-forward
.
$ kubectl get pods NAME READY STATUS RESTARTS AGE demoapp-84b67c64c8-24lvj 1/1 Running 0 2d
Then note the pod name and run:
$kubectl port-forward demoapp-84b67c64c8-24lvj 8080
Now you’ll be able to curl
to your pod:
$ curl -X GET http://localhost:8080/hello
##Extend the pipeline
Now that the k8s deployment is working, the k8s cluster is up’n running, we want to deploy our code to AKS. Doing so requires a few steps:
NOTE: All these steps are in the Microsoft documentation
#!/bin/bash AKS_RESOURCE_GROUP=myAKSResourceGroup AKS_CLUSTER_NAME=myAKSCluster ACR_RESOURCE_GROUP=myACRResourceGroup ACR_NAME=myACRRegistry # Get the id of the service principal configured for AKS CLIENT_ID=$(az aks show --resource-group $AKS_RESOURCE_GROUP --name $AKS_CLUSTER_NAME --query "servicePrincipalProfile.clientId" --output tsv) # Get the ACR registry resource id ACR_ID=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query "id" --output tsv) # Create role assignment az role assignment create --assignee $CLIENT_ID --role acrpull --scope $ACR_ID
Save the file, make it executable with:
$ chmod +x <scriptname>
Afterwards, login to AKS and set the subscription:
$ az login -u <your user name> $ az account set -s <your subscription>
Note that you will be challenged for your password. upon login.
Then execute your grant script from above
azure-pipelines.yml
:
variables: azureSubscriptionEndpoint: <your new service connection> azureContainerRegistry: <yourregistry>.azurecr.io azureResourceGroup: <your resource group> kubernetesCluster: <your clustername> steps:
task: Kubernetes@1 displayName: ‘kubectl login’ inputs: connectionType: ‘Azure Resource Manager’ azureSubscriptionEndpoint: $(azureSubscriptionEndpoint) azureResourceGroup: $(azureResourceGroup) kubernetesCluster: $(kubernetesCluster) command: login
task: Kubernetes@1 displayName: kubectl apply inputs: connectionType: ‘Azure Resource Manager’ azureSubscriptionEndpoint: $(azureSubscriptionEndpoint) azureResourceGroup: $(azureResourceGroup) kubernetesCluster: $(kubernetesCluster) command: apply arguments: -f manifests/deployment.yml
</pre>
$ kubectl get pods
you will discover that your pod has a state of ImagePullBackOff
or ErrImagePull
. If you dig deeper with:
$ kubectl describe pod <pod name>
the event log will tell you that it failed to pull the docker image, with an authentication problem.
To fix this, you need to extend the deployment.yml
from:
: containers: - name: demoapp imagePullPolicy: IfNotPresent image: nemoregistrysandbox.azurecr.io/demoapp ports: - containerPort: 8080
with the pullsecrets:
: containers: - name: demoapp imagePullPolicy: IfNotPresent image: nemoregistrysandbox.azurecr.io/demoapp ports: - containerPort: 8080 imagePullSecrets: - name: acr-auth
Now, that you reference the act-auth
image pull secrets, you need to define them within the cluster. This can be achieved
by different methods. First, by using kubectl
on the command line. However, this would be a manual step that we
need to avoid (at all cost, to be honest).
So, instead we’re creating a YAML file that we can deploy in an automated way. Therefore we need to create a
new yaml file that will let us deploy the secrets.
docker login
, which then creates
a .docker/config.json
file in your HOME directory. Run the follwing command and copy the output:
$ cat ~/.docker/config.json | base64
Create a new file named manifests/pullsecrets.yml
with the following content:
apiVersion: v1 kind: Secret metadata: name: acr-pullsecrets namespace: default data: .dockerconfigjson: <your base64 encoded ~/<user>/.docker/config.json file> type: kubernetes.io/dockerconfigjson
kubectl
magic:
$ kubectl get ns $ kubectl get pods --all-namespaces $ kubectl describe pod <pod name> $ kubectl port-forward <pod name> 8080
curl
:
$ curl -X GET http://localhost:8080/hello