From command line
Prague people live on 95 years on average
Prague people live on 95 years on average
# # awesome kuebectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
Overview
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# Create Namesace kubectl create namespace <some_name> # ******************************* # ResourceQuota Examples # ******************************* apiVersion: v1 kind: Namespace metadata: name: myspace --- apiVersion: v1 kind: ResourceQuota metadata: name: compute-quota namespace: myspace spec: hard: requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi --- apiVersion: v1 kind: ResourceQuota metadata: name: object-quota namespace: myspace spec: hard: configmaps: "10" persistentvolumeclaims: "4" replicationcontrollers: "20" secrets: "10" services: "10" services.loadbalancers: "2" |
1 2 3 4 5 6 7 8 9 |
kubectl describe quota compute-quota --namespace=myspace Name: compute-quota Namespace: myspace Resource Used Hard -------- ---- ---- limits.cpu 0 2 limits.memory 0 2Gi requests.cpu 0 1 requests.memory 0 1Gi |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
kubectl get quota --namespace=myspace NAME AGE compute-quota 44m object-quota 44m jantoth@ubuntu-ansible:~/kubernetes-course/resourcequotas$ kubectl describe quota compute-quota --namespace=myspace Name: compute-quota Namespace: myspace Resource Used Hard -------- ---- ---- limits.cpu 800m 2 limits.memory 2Gi 2Gi requests.cpu 400m 1 requests.memory 1Gi 1Gi jantoth@ubuntu-ansible:~/kubernetes-course/resourcequotas$ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
kubectl create -f defaults.yml limitrange "limits" created jantoth@ubuntu-ansible:~/kubernetes-course/resourcequotas$ kubectl describe limits limits --namespace=myspace Name: limits Namespace: myspace Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio ---- -------- --- --- --------------- ------------- ----------------------- Container memory - - 256Mi 512Mi - Container cpu - - 100m 200m - jantoth@ubuntu-ansible:~/kubernetes-course/resourcequotas$ cat defaults.yml apiVersion: v1 kind: LimitRange metadata: name: limits namespace: myspace spec: limits: - default: cpu: 200m memory: 512Mi defaultRequest: cpu: 100m memory: 256Mi type: Container |
Overview This section will provide insight to auto scaling on kubernetes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# ************************************** # HorizontalPodAutoscaler # ************************************** cat hpa-example.yml ... apiVersion: extensions/v1beta1 kind: Deployment metadata: name: hpa-example spec: replicas: 3 template: metadata: labels: app: hpa-example spec: containers: - name: hpa-example image: gcr.io/google_containers/hpa-example ports: - name: http-port containerPort: 80 resources: requests: cpu: 200m --- apiVersion: v1 kind: Service metadata: name: hpa-example spec: ports: - port: 31001 nodePort: 31001 targetPort: http-port protocol: TCP selector: app: hpa-example type: NodePort --- apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: hpa-example-autoscaler spec: scaleTargetRef: apiVersion: extensions/v1beta1 kind: Deployment name: hpa-example minReplicas: 1 maxReplicas: 10 targetCPUUtilizationPercentage: 50 |
Overview
1 2 3 4 5 6 7 8 9 10 |
# ******************************* # Create kubernetes cluster on # AWS with dashboard # ******************************* kops create cluster --name=kops.linuxinuse.com --state=s3://kops-state-kx2b6219 --zones=eu-central-1a --node-count=2 --node-size=t2.micro --master-size=t2.micro --dns-zone=kops.linuxinuse.com kops update cluster kops.linuxinuse.com --yes --state=s3://kops-state-kx2b6219 kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/alternative/kubernetes-dashboard.yaml |
heapster configuration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# # heapster.yaml # apiVersion: v1 kind: ServiceAccount metadata: name: heapster namespace: kube-system --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: heapster namespace: kube-system spec: replicas: 1 template: metadata: labels: task: monitoring k8s-app: heapster spec: serviceAccountName: heapster containers: - name: heapster image: k8s.gcr.io/heapster-amd64:v1.4.2 imagePullPolicy: IfNotPresent command: - /heapster - --source=kubernetes:https://kubernetes.default - --sink=influxdb:http://monitoring-influxdb.kube-system.svc:8086 --- apiVersion: v1 kind: Service metadata: labels: task: monitoring # For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons) # If you are NOT using this as an addon, you should comment out this line. # kubernetes.io/cluster-service: 'true' kubernetes.io/name: Heapster name: heapster namespace: kube-system spec: ports: - port: 80 targetPort: 8082 selector: k8s-app: heapster |
influxdb configuration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# # influxdb.yaml # apiVersion: extensions/v1beta1 kind: Deployment metadata: name: monitoring-influxdb namespace: kube-system spec: replicas: 1 template: metadata: labels: task: monitoring k8s-app: influxdb spec: containers: - name: influxdb image: k8s.gcr.io/heapster-influxdb-amd64:v1.3.3 volumeMounts: - mountPath: /data name: influxdb-storage volumes: - name: influxdb-storage emptyDir: {} --- apiVersion: v1 kind: Service metadata: labels: task: monitoring # For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons) # If you are NOT using this as an addon, you should comment out this line. # kubernetes.io/cluster-service: 'true' kubernetes.io/name: monitoring-influxdb name: monitoring-influxdb namespace: kube-system spec: ports: - port: 8086 targetPort: 8086 selector: k8s-app: influxdb |
grafana configuration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# # grafana.yaml # #apiVersion: v1 apiVersion: extensions/v1beta1 kind: Deployment metadata: name: monitoring-grafana namespace: kube-system spec: replicas: 1 template: metadata: labels: task: monitoring k8s-app: grafana spec: containers: - name: grafana image: k8s.gcr.io/heapster-grafana-amd64:v4.4.3 ports: - containerPort: 3000 protocol: TCP volumeMounts: - mountPath: /etc/ssl/certs name: ca-certificates readOnly: true - mountPath: /var name: grafana-storage env: - name: INFLUXDB_HOST value: monitoring-influxdb - name: GF_SERVER_HTTP_PORT value: "3000" # The following env variables are required to make Grafana accessible via # the kubernetes api-server proxy. On production clusters, we recommend # removing these env variables, setup auth for grafana, and expose the grafana # service using a LoadBalancer or a public IP. - name: GF_AUTH_BASIC_ENABLED value: "false" - name: GF_AUTH_ANONYMOUS_ENABLED value: "true" - name: GF_AUTH_ANONYMOUS_ORG_ROLE value: Admin - name: GF_SERVER_ROOT_URL # If you're only using the API Server proxy, set this value instead: # value: /api/v1/namespaces/kube-system/services/monitoring-grafana/proxy value: / volumes: - name: ca-certificates hostPath: path: /etc/ssl/certs - name: grafana-storage emptyDir: {} --- apiVersion: v1 kind: Service metadata: labels: # For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons) # If you are NOT using this as an addon, you should comment out this line. # kubernetes.io/cluster-service: 'true' kubernetes.io/name: monitoring-grafana name: monitoring-grafana namespace: kube-system spec: # In a production setup, we recommend accessing Grafana through an external Loadbalancer # or through a public IP. # type: LoadBalancer # You could also use NodePort to expose the service at a randomly-generated port type: NodePort ports: - port: 80 targetPort: 3000 selector: k8s-app: grafana |
Overview Storage GP2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# ******************************** # create storage # ******************************** cat storage.yml kind: StorageClass apiVersion: storage.k8s.io/v1beta1 metadata: name: standard provisioner: kubernetes.io/aws-ebs parameters: type: gp2 zone: eu-central-1a |
get all storages
1 2 3 4 5 |
kubectl get sc NAME PROVISIONER AGE default kubernetes.io/aws-ebs 1h gp2 (default) kubernetes.io/aws-ebs 1h standard kubernetes.io/aws-ebs 5m |
Example of usage GP2 general purpose storage on AWS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# ******************************** # mount GP2 - general purpose # storage # ******************************** cat helloworld-with-volume.yml ... apiVersion: extensions/v1beta1 kind: Deployment metadata: name: helloworld-deployment spec: replicas: 1 template: metadata: labels: app: helloworld spec: containers: - name: k8s-demo image: wardviaene/k8s-demo ports: - name: nodejs-port containerPort: 3000 volumeMounts: - mountPath: /myvol name: myvolume volumes: - name: myvolume awsElasticBlockStore: volumeID: # insert AWS EBS volumeID here |
Volume claim
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# ********************************* # something like pattern for GP2 # storage volume # ********************************* cat pv-claim.yml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: db-storage annotations: volume.beta.kubernetes.io/storage-class: "standard" spec: accessModes: - ReadWriteOnce resources: requests: storage: 8Gi |
Get/list persistent volume claim
1 2 3 |
kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE db-storage Bound pvc-410d57ef-f5ef-11e7-b6dd-02f7313a206c 8Gi RWO standard 13s |
NFS filesystem on AWS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# ************************ # create NFS on AWS # ************************ aws efs create-file-system --creation-token 1020201 { "LifeCycleState": "creating", "OwnerId": "226106667391", "CreationToken": "10202018", "FileSystemId": "fs-10a44c49", "SizeInBytes": { "Value": 0 }, "CreationTime": 1515583187.0, "Encrypted": false, "PerformanceMode": "generalPurpose", "NumberOfMountTargets": 0 } aws efs create-mount-target --file-system-id fs-10a44c49 --subnet-id subnet-44f96a2f --security-groups sg-bf8aa3d5 { "FileSystemId": "fs-10a44c49", "IpAddress": "172.20.37.207", "OwnerId": "226106667391", "MountTargetId": "fsmt-b5a44fec", "NetworkInterfaceId": "eni-e25e16b7", "SubnetId": "subnet-44f96a2f", "LifeCycleState": "creating" } |
Oveview Create your first configmap out of file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# ******************************* # create some dummy configuration # file first # ******************************* cat << EOF > app.properties driver=jdbc database=postgres lookandfeel=1 otherparams=xzy EOF # ******************************* # Create configmap with name: # - "app-config" # ******************************* cat app.properties kubectl create configmap app-config --from-file=app.properties kubectl get configmaps kubectl describe configmap app-config Name: app-config Namespace: default Labels: <none> Annotations: <none> Data ==== app.properties: ---- driver=jdbc database=postgres lookandfeel=1 otherparams=xzy Events: <none> |
Create nginx-config confimap object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# ********************************* # Our custom Nginx configuration # file # ********************************* cat reverseproxy.conf server { listen 80; server_name localhost; location / { proxy_bind 127.0.0.1; proxy_pass http://127.0.0.1:3000; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } # ********************************* # create nginx-config configmap # ********************************* kubectl create configmap nginx-config --from-file=reverseproxy.conf # ********************************* # show all available configmaps # ********************************* kubectl get configmaps NAME DATA AGE app-config 1 12m nginx-config 1 3m # ********************************* # describe "nginx-configmap" # ********************************* kubectl describe configmap nginx-config ... Data ==== reverseproxy.conf: ---- server { listen 80; server_name localhost; location / { proxy_bind 127.0.0.1; proxy_pass http://127.0.0.1:3000; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } Events: <none> ... |
Nginx service
1 2 3 4 5 6 7 8 9 10 11 |
apiVersion: v1 kind: Service metadata: name: helloworld-nginx-service spec: ports: - port: 80 protocol: TCP selector: app: helloworld-nginx type: NodePort |
Nginx pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
apiVersion: v1 kind: Pod metadata: name: helloworld-nginx labels: app: helloworld-nginx spec: containers: - name: nginx image: nginx:1.11 ports: - containerPort: 80 volumeMounts: - name: config-volume mountPath: /etc/nginx/conf.d - name: k8s-demo image: wardviaene/k8s-demo ports: - containerPort: 3000 volumes: - name: config-volume configMap: name: nginx-config items: - key: reverseproxy.conf path: reverseproxy.conf |
In order to log in to particular container within pod there is some useful command below.
1 2 3 4 5 6 7 8 |
# **************************************************** # this pod "helloworld-nginx" has 2 containers inside # # helloworld-nginx - is a pod # -c nginx - is a container # **************************************************** kubectl exec -it helloworld-nginx -c nginx -- bash |
Overview In this demonstration we will create a sequence for: secret definition mysql pod mysql service deployment defionition deployment service Create credential file
1 2 3 4 5 6 7 8 9 10 |
apiVersion: v1 kind: Secret metadata: name: helloworld-secrets type: Opaque data: username: aGVsbG93b3JsZA== password: cGFzc3dvcmQ= rootPassword: cm9vdHBhc3N3b3Jk database: aGVsbG93b3JsZA== |
Create mysql pod with this definition
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# *********************** # mysql pod # *********************** cat database.yml ... apiVersion: v1 kind: Pod metadata: name: database labels: app: database spec: containers: - name: mysql image: mysql:5.7 ports: - name: mysql-port containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: helloworld-secrets key: rootPassword - name: MYSQL_USER valueFrom: secretKeyRef: name: helloworld-secrets key: username - name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: helloworld-secrets key: password - name: MYSQL_DATABASE valueFrom: secretKeyRef: name: helloworld-secrets key: database ... :wq! |
On the top of this deployment.yml pod the service definition is necessary.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
cat database-service.yml ... apiVersion: v1 kind: Service metadata: name: database-service spec: ports: - port: 3306 protocol: TCP selector: app: database type: NodePort ... :wq! |
Deployment
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
cat helloworld-db.yml ... apiVersion: extensions/v1beta1 kind: Deployment metadata: name: helloworld-deployment spec: replicas: 3 template: metadata: labels: app: helloworld-db spec: containers: - name: k8s-demo image: wardviaene/k8s-demo command: ["node", "index-db.js"] ports: - name: nodejs-port containerPort: 3000 env: - name: MYSQL_HOST value: database-service - name: MYSQL_USER value: root - name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: helloworld-secrets key: rootPassword - name: MYSQL_DATABASE valueFrom: secretKeyRef: name: helloworld-secrets key: database ... :wq! |
Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
helloworld-db-service.yml ... apiVersion: v1 kind: Service metadata: name: helloworld-db-service spec: ports: - port: 3000 protocol: TCP selector: app: helloworld-db type: NodePort ... :wq! |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# *********************************** # get all pods available # # *********************************** kubectl get pods NAME READY STATUS RESTARTS AGE database 1/1 Running 0 4h helloworld-deployment-54dfb95d8c-8m6fk 1/1 Running 0 9m helloworld-deployment-54dfb95d8c-s8rdf 1/1 Running 0 9m helloworld-deployment-54dfb95d8c-x5xqk 1/1 Running 0 9m # *********************************** # login to database - to "database" # pod # *********************************** kubectl exec database -it -- mysql -u root -p Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> mysql> mysql> show databases ; +--------------------+ | Database | +--------------------+ | information_schema | | helloworld | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) |
[…]
Overview
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# *********************************************** # get credentials to your kubernetes cluster # *********************************************** kubectl config view # *********************************************** # this command will show you "hidden" pods # for example: # - DNS pod # - ... # *********************************************** kubectl get pods --kubesystem # *********************************************** # describe "hidden" pod # this pod is runnig in default namespace # *********************************************** kubectl describe pod dns-controller-6f12337cd98f-vrj6f --namespace=kube-system # *********************************************** # SSH to DNS pod in "hidden" default namespace # # *********************************************** kubectl exec -it dns-controller-6ff67sdffsd98f-vrj6f \ --namespace=kube-system -- sh # *********************************************** # SSH to CLUSTER node # # we have cluster : - master # - node1 # - node2 # # the IP address I am referencing in below command # can be easily found in AWS dashboard # # *********************************************** ssh -i /home/user/.ssh/id_rsa -l admin 52.91.217.134 <span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1"></span> |
1 2 3 4 5 6 7 8 9 10 |
# ***************************************** # Dashboard UI # ***************************************** kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/alternative/kubernetes-dashboard.yaml serviceaccount "kubernetes-dashboard" unchanged role "kubernetes-dashboard-minimal" configured rolebinding "kubernetes-dashboard-minimal" unchanged deployment "kubernetes-dashboard" configured service "kubernetes-dashboard" configured |
Overview This particular example is interesting cause we are going to use 2 containers within one POD with only one replica. This example will represent state full application which is not a good concept at all however, it is very good for learning purposes. Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# ********************************* # Set up a service # ********************************* cat wordpress/wordpress-service.yml ... apiVersion: v1 kind: Service metadata: name: wordpress-service spec: ports: - port: 31001 nodePort: 31001 targetPort: http-port protocol: TCP selector: app: wordpress type: NodePort ... :wq! |
Secret
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# ********************************* # Set up some credentials # ********************************* cat wordpress/wordpress-secrets.yml ... apiVersion: v1 kind: Secret metadata: name: wordpress-secrets type: Opaque data: db-password: cGFzc3dvcmQ= ... :wq! |
Deployment
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# **************************************************** # Deployment of wordpress and MySQL database # **************************************************** cat wordpress/wordpress-single-deployment-no-volumes.yml ... apiVersion: extensions/v1beta1 kind: Deployment metadata: name: wordpress-deployment spec: replicas: 1 template: metadata: labels: app: wordpress spec: containers: - name: wordpress image: wordpress:4-php7.0 ports: - name: http-port containerPort: 80 env: - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: wordpress-secrets key: db-password - name: WORDPRESS_DB_HOST value: 127.0.0.1 - name: mysql image: mysql:5.7 ports: - name: mysql-port containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: wordpress-secrets key: db-password ... :wq! |
Devops blog 2024 | All Rights Reserved