Kubernetes - studiofu/brain GitHub Wiki

Quick Start

Install microk8s by using snap

https://microk8s.io/

你的第一次轻量级K8S体验 —— 记一次Rancher 2.2 + K3S集成部署过程

https://blog.ilemonrain.com/docker/rancher-with-k3s.html

CentOS 7.6上安裝 Kubernetes(一)叢集佈署

https://blog.tomy168.com/2019/08/centos-76-kubernetes.html

Kubernetes 30天學習筆記

https://ithelp.ithome.com.tw/articles/10193232

15 分鐘學習系列 - 第一次學 Kubernetes 就上手系列

https://ithelp.ithome.com.tw/articles/10202177

JD Story

https://kubernetes.io/blog/2017/02/inside-jd-com-shift-to-kubernetes-from-openstack/

Setting up a distributed Kubernetes cluster along with Istio service mesh locally with Vagrant and VirtualBox

https://github.com/rootsongjc/kubernetes-vagrant-centos-cluster

using helm

https://medium.com/@C.W.Hu/kubernetes-helm-chart-tutorial-fbdad62a8b61

build docker using Dockerfile

docker build .

docker build . -t foosi/demo:v2

FROM node:6.2.2
WORKDIR /app
ADD ./app /app
RUN npm install
EXPOSE 3000
CMD npm start

run the docker with port mapping -p [local]:[container]

docker run -p 3000:3000 -it [image-id]

tag the image

docker tag image-id foosi/docker-demo

push to docker hub

docker push foosi/docker-demo

push image

docker pull nginx

k8s pod

one pod contains more than one container

define pod by using yaml

# my-first-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: webserver
spec:
  containers:
  - name: pod-demo
    image: zxcvbnius/docker-demo
    ports:
    - containerPort: 3000

use k8s to run the container

kubectl create -f my-first-pod.yaml

check pods

kubectl get pods

check pods information

kubectl describe pods [pods]

expose the port

kubectl port-forward my-pod 8000:3000

expose the service

kubectl expose pod my-pod --type=NodePort --name=my-pod-service

check service

kubectl get services

attach to the pod

kubectl attach [pod-name] -i

exec command

kubectl exec [pod] -- ls

define the container name if more than one containers in the pod

kubectl exec -it hello-deployment-67f4dc5cf-7g9kr --container my-alpine -- bash

check label

kubectl get pods --show-labels

apply label

kubectl label pods my-pods version=latest

create pod for checking another container

kubectl run -i --tty alpine --image=alpine --restart=Never -- sh

apk add curl

need to know the different of cluster ip and the pod ip

node is the physical machine or virtual machine

check node kubectl get nodes

architecture

client => load balance => node / node / node / ... => iptable => [kubelet | kube-proxy ] / pod1 - container

kubelet is node agent and use to communicate with master node kube-proxy is used to update iptable with the latest pod information

define rc yaml

apiVersion: v1
kind: ReplicationController
metadata:
  name: my-replication-controller
spec:
  replicas: 3
  selector:
    app: hello-pod-v1
  template:
    metadata:
      labels:
        app: hello-pod-v1
    spec:
      containers:
      - name: my-pod
        image: zxcvbnius/docker-demo
        ports:
        - containerPort: 3000

check rc

kubectl get rc

scale rc

kubectl scale --replicas=4 -f ./my-replication-controller.yaml

use deployment instead of directly using rc or rs

check deployment

define replica

apiVersion: apps/v1 # for kubectl versions >= 1.9.0 use apps/v1
kind: ReplicaSet
metadata:
  name: my-replica-set
spec:
  replicas: 3
  selector:
    matchLabels:
      env: dev
    matchExpressions:
      - {key: env, operator: In, values: [dev]}
      - {key: env, operator: NotIn, values: [prod]}
  template:
    metadata:
      labels:
        app: hello-pod-v1
        env: dev
        version: v1
    spec:
      containers:
      - name: my-pod
        image: zxcvbnius/docker-demo
        ports:
        - containerPort: 3000

define deployment

apiVersion: apps/v1 # for kubectl versions >= 1.9.0 use apps/v1
kind: Deployment
metadata:
  name: hello-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-deployment
  template:
    metadata:
      labels:
        app: my-deployment
    spec:
      containers:
      - name: my-pod
        image: zxcvbnius/docker-demo:latest
        ports:
        - containerPort: 3000

kubectl describe deployment [deployment-id]

kubectl get all

expose deployment

kubectl expose deploy hello-deployment --type=NodePort --name=my-deployment-service

upgrade image

upgrade the image in the hello-deployment

kubectl set image deploy/hello-deployment my-pod=zxcvbnius/docker-demo:v2.0.0

check rollout status

kubectl rollout status deploy hello-deployment

use edit to edit the image

kubectl edit deploy hello-deployment

check rollout history

kubectl rollout history deploy hello-deployment

undo

kubectl rollout undo deployment hello-deployment

define service

apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  type: NodePort
  ports:
  - port: 3000
    nodePort: 30390
    protocol: TCP
    targetPort: 3000
  selector:
    app: my-deployment

the service is created for the deployment with the label app: my-deployment

define pod with labels and also with node selector

### ResourcesapiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: webserver
    tier: backend
  annotations:
    version: latest
    release_date: 2017/12/28
    contact: [email protected]
spec:
  containers:
  - name: pod-demo
    image: zxcvbnius/docker-demo
    ports:
    - containerPort: 3000
  nodeSelector:
    hardware: high-memory

the node must have the label hardware: high-memory

apply the label to node

kubectl label node minikube hardware=high-memory

create deployment with health checking

apiVersion: apps/v1beta2 # for kubectl versions >= 1.9.0 use apps/v1
kind: Deployment
metadata:
  name: hello-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-deployment
  template:
    metadata:
      labels:
        app: my-deployment
    spec:
      containers:
      - name: webapp
        image: zxcvbnius/docker-demo
        ports:
        - name: webapp-port
          containerPort: 3000
        livenessProbe:
          httpGet:
            path: /
            port: webapp-port
          initialDelaySeconds: 15
          periodSeconds: 15
          timeoutSeconds: 30  
          successThreshold: 1
          failureThreshold: 3

use http to check the health status

in production, there is an end-point, for example, /health to return the status

secret

from command

kubectl create secret generic demo-secret-from-literal \
> --from-literal=username=root \
> --from-literal=password=rootpass

from yaml

apiVersion: v1
kind: Secret
metadata:
  name: demo-secret-from-yaml
type: Opaque
data:
  username: cm9vdA==
  password: cm9vdHBhc3M=

apply the secret to pod environment variable

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: webserver
spec:
  containers:
  - name: demo-pod
    image: zxcvbnius/docker-demo
    ports:
    - containerPort: 3000
    env:
    - name: SECRET_USERNAME
      valueFrom:
        secretKeyRef:
          name: demo-secret-from-yaml
          key: username
    - name: SECRET_PASSWORD
      valueFrom:
        secretKeyRef:
          name: demo-secret-from-yaml
          key: password

apply the secret to volume

apiVersion: v1
kind: Pod
metadata:
  name: my-pod-with-mounting-secret
  labels:
    app: webserver
spec:
  containers:
  - name: demo-pod
    image: zxcvbnius/docker-demo
    ports:
    - containerPort: 3000
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/creds
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: demo-secret-from-yaml

example to install wordpress to k8s environment

define secret for mysql root password

apiVersion: v1
kind: Secret
metadata:
  name: wordpress-secret
type: Opaque
data:
  # echo -n "rootpass" | base64
  db-password: cm9vdHBhc3M=

apply the deployment

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: wordpress-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress-deployment
  template:
    metadata:
      labels:
        app: wordpress-deployment
    spec:
      containers:
      - name: wordpress
        image: wordpress:4-php7.0
        ports:
        - name: wordpress-port
          containerPort: 80
        env:
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: wordpress-secret
              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-secret
              key: db-password

enable dashboard in minikube

minikube dashboard

use kops to manage aws

refer to the ithelp tutorial

k8s service discovery dns

kube-dns or coredns helps pods to find each other by using the service name

after expose the service, just need to use service name to find each other

example:

create mysql

apiVersion: v1
kind: Pod
metadata: 
  name: mysql-server
  labels:
    app: mysql-server
spec:
  containers:
  - name: mysql-server
    image: mysql:5.7
    ports: 
    - name: mysql-port
      containerPort: 3306
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysql-secret
          key: db-root-password

create mysql service mysql-server-service

apiVersion: v1
kind: Service
metadata:
  name: mysql-server-service
spec:
  ports:
  - port: 3306
    protocol: TCP
  selector:
    app: mysql-server
  type: NodePort

create the worldpress web service and then connect to the database using the mysql service name


apiVersion: v1
kind: Pod
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  containers:
  - name: wordpress
    image: wordpress:4-php7.0
    ports:
    - name: wordpress-port
      containerPort: 80
    env:
    - name: WORDPRESS_DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysql-secret
          key: db-root-password
    - name: WORDPRESS_DB_HOST
      value: mysql-server-service

expose the deployment

apiVersion: v1
kind: Service
metadata:
  name: wordpress-service
spec:
  ports:
  - port: 3000
    nodePort: 30300
    protocol: TCP
    targetPort: wordpress-port
  selector:
    app: wordpress
  type: NodePort

using config map to store configuration for pods

nginx example

define a nginx config and store to the config map

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 the config map

kubectl create configmap nginx-conf --from-file=./my-nginx.conf

define the pod which use the nodejs image and also the nginx and apply the config from config map to nginx

apiVersion: v1
kind: Pod
metadata:
  name: apiserver
  labels:
    app: webserver
    tier: backend
spec:
  containers:
  - name: nodejs-app
    image: zxcvbnius/docker-demo
    ports:
    - containerPort: 3000
  - name: nginx
    image: nginx:1.13
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-conf-volume
      mountPath: /etc/nginx/conf.d
  volumes:
  - name: nginx-conf-volume
    configMap:
      name: nginx-conf
      items:
      - key: my-nginx.conf
        path: my-nginx.conf
mount single file
    - name: nginx-conf-volume
      mountPath: /etc/nginx/conf.d/my-nginx.conf
      subPath: my-nginx.conf

expose the svc for of port 80

kubectl expose pod apiserver --port=80 --type=NodePort

use ingress controller for the load balancing

maybe classify ingress as load balancing is not very correct

it should be used to route the inbound traffic according to the rules to the specific services

route /test to the service test

need to install ingress to cluster, in bare-metal environment, we could only expose the ingress through a NodePort

from ingress site, install the mandatory.yaml and then install service-nodeport.yaml, ingress service could be used through the node port.

#k get svc -n ingress-nginx
NAME            TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.110.197.107   <none>        80:30096/TCP,443:31198/TCP   22h

#k get ingress
NAME                 HOSTS                            ADDRESS          PORTS   AGE
helloworld-ingress   helloworld.192.168.1.60.nip.io   10.110.197.107   80      22h
web                  blue.demo.com,purple.demo.com    10.110.197.107   80      22h

access through blue.demo.com:30096 or purple.demo.com:30096 or helloworld.192.168.1.60.nip.io:30096
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: example-1
spec:
  rules:
  - http:
      paths:
      - path: /test
        backend:
          serviceName: test
          servicePort: 80

route helloworld-v1.example.com and helloworld-v2.example.com to the corresponding services

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: example-2
spec:
  rules:
  - host: helloworld-v1.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: hellworld-v1
          servicePort: 80
  - host: helloworld-v2.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: helloworld-v2
          servicePort: 80

use namespace to create a virtual cluster to seperate the pods and containers

Sample ingress yaml

#example.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: aks-helloworld-one
spec:
  replicas: 1
  selector:
    matchLabels:
      app: aks-helloworld-one
  template:
    metadata:
      labels:
        app: aks-helloworld-one
    spec:
      containers:
      - name: aks-helloworld-one
        #image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
        image: k8s.gcr.io/hpa-example
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: aks-helloworld-one
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  selector:
    app: aks-helloworld-one
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: aks-helloworld-one
  annotations:
    kubernetes.io/ingress.class: azure/application-gateway
spec:
  rules:
  - host: aido.hynes.pri
    http:
      paths:
      - backend:
          serviceName: aks-helloworld-one
          servicePort: 80
        path: /
#example.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: aks-helloworld-two
spec:
  replicas: 1
  selector:
    matchLabels:
      app: aks-helloworld-two
  template:
    metadata:
      labels:
        app: aks-helloworld-two
    spec:
      containers:
      - name: aks-helloworld-two
        #image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
        image: k8s.gcr.io/hpa-example
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: aks-helloworld-two
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  selector:
    app: aks-helloworld-two
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: aks-helloworld-two
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - host: bido.hynes.pri
    http:
      paths:
      - backend:
          serviceName: aks-helloworld-two
          servicePort: 80
        path: /(.*)

Resources

Basic Introduction

https://blog.gcp.expert/kubernetes-gke-introduction/

https://blog.gcp.expert/tutorials-kubernetes-engine-load-balancer/

Baisc Tutorial

https://ithelp.ithome.com.tw/articles/10192490

Install kubectl

https://kubernetes.io/docs/tasks/tools/install-kubectl/

Install minikube for testing

https://github.com/kubernetes/minikube

https://kubernetes.io/

minikube - local kubernetes cluster for learning, testing and development, need to use virtual box

https://github.com/kubernetes/minikube

kubernetes interactive tutorial

https://www.katacoda.com/courses/kubernetes

Deploying Java Applications with Docker and Kubernetes

https://www.oreilly.com/ideas/how-to-manage-docker-containers-in-kubernetes-with-java

使用Kubernetes和Ambassador API Gateway部署Java应用程序

https://cloud.tencent.com/developer/article/1367191

Kubernetes的三种外部访问方式:NodePort、LoadBalancer和Ingress

https://www.cnblogs.com/blogabc/p/10037301.html

mutiple containers in a pod

https://linchpiner.github.io/k8s-multi-container-pods.html

⚠️ **GitHub.com Fallback** ⚠️