Kubernetes practice
April 28, 2023

Create ns deploy nginx + qos + probe + pc + quota + cm + secret + pv(emptyDir) + svc + pdb + hpa

Разберём в этом примере взаимодействие разных компонентов кластера. Начнём с Namespace, PriorityClass, ResourceQuota. Затем создадим ConfigMap, Secret, Deployment c QOS burstable. Потом с помощью Service сделаем веб сайт доступным извне. Затем добавим PDB и HPA.

Создаём Namespace.

kubectl create ns test

Создаём PriorityClass. Создадим в начале PriorityClass для Deployment с Nginx. Это увеличит надёжность работы и предотвратит эвакуацию подов на другую ноду.

cat <<EOF | kubectl apply -f -
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: cam-pc
  namespace: test
  labels:
    pc: test
  annotations:
    author: cameda
value: 50
globalDefault: false
description: "This priority class should be used for nginx only."
EOF

Данный класс будет навешиваться только на те ресурсы, где он будет явно указан. Значение в 50 гораздо ниже, чем у системных подов, но выше чем дефолтное значение, равное нулю.

Проверяем, что PriorityClass правильно установлен:

kubectl get pc -n test
NAME                      VALUE        GLOBAL-DEFAULT   AGE
cam-pc                    50           false            14s

Создаём ResourceQuota.

Эта сущность необходима для разграничения ресурсов между namespace в кластере. Чтобы ресурсы (поды) из одного ns не монополизировали все ресурсы кластера.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ResourceQuota
metadata:
  name: cam-resquota
  namespace: test
  labels:
    quota: test
  annotations:
    author: cameda
spec:
  hard:
    cpu: "30"
    memory: 30Gi
    pods: "90"
  scopeSelector:
    matchExpressions:
    - operator : In
      scopeName: PriorityClass
      values: ["cam-pc"]
EOF

Указываем в PriorityClass имя ранее созданного класса.

Проверяем, что квоты правильно установлены:

kubectl get quota -n test
NAME           AGE   REQUEST                                  LIMIT
cam-resquota   60s   cpu: 0/1k, memory: 0/200Gi, pods: 0/30

Создаём Secret.

kubectl create secret generic cam-secret -n test --from-literal=cameda=goodPa$word

Создаём ConfigMap.

Файл /etc/nginx/site-available/default

server {
  listen 80 default_server;
  server_name cameda.ru;
  root /var/www/html/cameda1.ml;
  access_log off;

  location / {
    index.html;
  }
###########################################################################
  location ~ /\.ht {
    deny all;
  }
}

Создадим ConfigMap из этого файла.

kubectl create cm nginx-config -n test --from-file /etc/nginx/site-available/default

Создаём Deployment with PV+Secret+ConfigMap.

# kubectl create -f deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cameda-nginx
  namespace: test
  labels:
    app: nginx
    environment: test
  annotations:
    author: cameda
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  strategy: 
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - nginx 
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: nginx
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports: 
        - containerPort: 80
        - containerPort: 443  
        resources: 
          requests: 
            cpu: 300m
            memory: 300Mi 
          limits: 
            memory: 400Mi
        livenessProbe:
          failureThreshold: 10
          successThreshold: 1
          httpGet:
            path: /
            port: 80
          periodSeconds: 10
          timeoutSeconds: 1
          initialDelaySeconds: 5
        readinessProbe:
          failureThreshold: 3
          successThreshold: 1
          exec:
            command:
            - curl
            - http://127.0.0.1:80
          periodSeconds: 10
          timeoutSeconds: 1
          initialDelaySeconds: 7
        volumeMounts:
        - name: cam-emptydir
          mountPath: /mnt/emptydir
        - name: cam-secret
          mountPath: /etc/secret
          readOnly: true
        - name: cam-configmap
          mountPath: /etc/nginx/sites-available
          readOnly: true
      restartPolicy: Always
      priorityClassName: cam-pc
      dnsPolicy: ClusterFirst
      hostname: nginx
      subdomain: web
      serviceAccountName: default
      schedulerName: default-scheduler
      terminationGracePeriodSeconds: 90
      securityContext:
        runAsUser: 0
        runAsGroup: 0
        fsGroup: 2000
      tolerations:
      - key: "cam"
        operator: "Exists"
        effect: "NoSchedule"
      - key: "cam"
        operator: "Exists"
        effect: "NoExecute"
      volumes:
      - name: cam-emptydir
        emptyDir: {}
      - name: cam-secret
        secret:
          secretName: cam-secret
      - name: cam-configmap
        configMap:
          name: nginx-config

Создаём Service.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  namespace: test
  name: cam-service-nginx
  labels:
    environment: prod
    svc: nginx
  annotations:
    author: cameda
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
  - name: https
    protocol: TCP
    port: 443
    targetPort: 443
EOF

Заработал Nginx.

curl http://84.201.171.218:31505/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Создаём PDB.

cat <<EOF | kubectl apply --validate=false -f -
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: cam-pdb
  namespace: test
  labels: 
    pdb: nginx-test
  annotations:
    author: cameda
spec:
  minAvailable: 1
  selector:
    matchLabels:
      app: nginx
EOF

Создаём HPA.

cat <<EOF | kubectl apply -f -
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: cam-hpa
  namespace: test
  labels: 
    hpa: nginx-test
  annotations:
    author: cameda
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: cameda-nginx
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 20
EOF