Kubernetes容器编排实战指南 概述 Kubernetes(K8s)是Google开源的容器编排平台,已成为云原生应用部署和管理的事实标准。本指南将从基础概念开始,逐步深入到高级实战应用,帮助读者全面掌握Kubernetes容器编排技术。
核心特性
自动化部署和回滚 :支持声明式配置和自动化部署
服务发现和负载均衡 :内置服务发现和流量分发机制
存储编排 :自动挂载存储系统,支持多种存储类型
自我修复 :自动重启失败容器,替换和重新调度节点
水平扩缩容 :根据CPU使用率或其他指标自动扩缩容
密钥和配置管理 :安全地管理敏感信息和应用配置
1. 集群架构与组件 控制平面组件 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 apiVersion: v1 kind: Pod metadata: name: kube-apiserver namespace: kube-system spec: containers: - name: kube-apiserver image: k8s.gcr.io/kube-apiserver:v1.28.0 command: - kube-apiserver - --advertise-address=192.168.1.100 - --allow-privileged=true - --authorization-mode=Node,RBAC - --client-ca-file=/etc/kubernetes/pki/ca.crt - --enable-admission-plugins=NodeRestriction - --enable-bootstrap-token-auth=true - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key - --etcd-servers=https://127.0.0.1:2379 - --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt - --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key - --requestheader-allowed-names=front-proxy-client - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt - --requestheader-extra-headers-prefix=X-Remote-Extra- - --requestheader-group-headers=X-Remote-Group - --requestheader-username-headers=X-Remote-User - --secure-port=6443 - --service-account-issuer=https://kubernetes.default.svc.cluster.local - --service-account-key-file=/etc/kubernetes/pki/sa.pub - --service-account-signing-key-file=/etc/kubernetes/pki/sa.key - --service-cluster-ip-range=10.96.0.0/12 - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key volumeMounts: - mountPath: /etc/ssl/certs name: ca-certs readOnly: true - mountPath: /etc/kubernetes/pki name: k8s-certs readOnly: true - mountPath: /usr/local/share/ca-certificates name: usr-local-share-ca-certificates readOnly: true - mountPath: /usr/share/ca-certificates name: usr-share-ca-certificates readOnly: true volumes: - hostPath: path: /etc/ssl/certs type: DirectoryOrCreate name: ca-certs - hostPath: path: /etc/kubernetes/pki type: DirectoryOrCreate name: k8s-certs - hostPath: path: /usr/local/share/ca-certificates type: DirectoryOrCreate name: usr-local-share-ca-certificates - hostPath: path: /usr/share/ca-certificates type: DirectoryOrCreate name: usr-share-ca-certificates --- apiVersion: v1 kind: Pod metadata: name: etcd namespace: kube-system spec: containers: - name: etcd image: k8s.gcr.io/etcd:3.5.9-0 command: - etcd - --advertise-client-urls=https://192.168.1.100:2379 - --cert-file=/etc/kubernetes/pki/etcd/server.crt - --client-cert-auth=true - --data-dir=/var/lib/etcd - --experimental-initial-corrupt-check=true - --experimental-watch-progress-notify-interval=5s - --initial-advertise-peer-urls=https://192.168.1.100:2380 - --initial-cluster=master=https://192.168.1.100:2380 - --key-file=/etc/kubernetes/pki/etcd/server.key - --listen-client-urls=https://127.0.0.1:2379,https://192.168.1.100:2379 - --listen-metrics-urls=http://127.0.0.1:2381 - --listen-peer-urls=https://192.168.1.100:2380 - --name=master - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt - --peer-client-cert-auth=true - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt - --snapshot-count=10000 - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt volumeMounts: - mountPath: /var/lib/etcd name: etcd-data - mountPath: /etc/kubernetes/pki/etcd name: etcd-certs volumes: - hostPath: path: /etc/kubernetes/pki/etcd type: DirectoryOrCreate name: etcd-certs - hostPath: path: /var/lib/etcd type: DirectoryOrCreate name: etcd-data --- apiVersion: v1 kind: Pod metadata: name: kube-controller-manager namespace: kube-system spec: containers: - name: kube-controller-manager image: k8s.gcr.io/kube-controller-manager:v1.28.0 command: - kube-controller-manager - --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf - --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf - --bind-address=127.0.0.1 - --client-ca-file=/etc/kubernetes/pki/ca.crt - --cluster-name=kubernetes - --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt - --cluster-signing-key-file=/etc/kubernetes/pki/ca.key - --controllers=*,bootstrapsigner,tokencleaner - --kubeconfig=/etc/kubernetes/controller-manager.conf - --leader-elect=true - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt - --root-ca-file=/etc/kubernetes/pki/ca.crt - --service-account-private-key-file=/etc/kubernetes/pki/sa.key - --service-cluster-ip-range=10.96.0.0/12 - --use-service-account-credentials=true volumeMounts: - mountPath: /etc/ssl/certs name: ca-certs readOnly: true - mountPath: /etc/ca-certificates name: etc-ca-certificates readOnly: true - mountPath: /etc/kubernetes/pki name: k8s-certs readOnly: true - mountPath: /etc/kubernetes/controller-manager.conf name: kubeconfig readOnly: true volumes: - hostPath: path: /etc/ssl/certs type: DirectoryOrCreate name: ca-certs - hostPath: path: /etc/ca-certificates type: DirectoryOrCreate name: etc-ca-certificates - hostPath: path: /etc/kubernetes/pki type: DirectoryOrCreate name: k8s-certs - hostPath: path: /etc/kubernetes/controller-manager.conf type: File name: kubeconfig --- apiVersion: v1 kind: Pod metadata: name: kube-scheduler namespace: kube-system spec: containers: - name: kube-scheduler image: k8s.gcr.io/kube-scheduler:v1.28.0 command: - kube-scheduler - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf - --bind-address=127.0.0.1 - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true volumeMounts: - mountPath: /etc/kubernetes/scheduler.conf name: kubeconfig readOnly: true volumes: - hostPath: path: /etc/kubernetes/scheduler.conf type: File name: kubeconfig
节点组件配置 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 apiVersion: v1 kind: ConfigMap metadata: name: kubelet-config namespace: kube-system data: kubelet: | apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration authentication: anonymous: enabled: false webhook: enabled: true x509: clientCAFile: /etc/kubernetes/pki/ca.crt authorization: mode: Webhook clusterDomain: cluster.local clusterDNS: - 10.96.0.10 cpuManagerPolicy: none evictionHard: imagefs.available: 15% memory.available: 100Mi nodefs.available: 10% nodefs.inodesFree: 5% failSwapOn: false hairpinMode: promiscuous-bridge healthzBindAddress: 127.0.0.1 healthzPort: 10248 httpCheckFrequency: 20s imageMinimumGCAge: 120s logging: flushFrequency: 5s options: json: infoBufferSize: "0" verbosity: 2 memorySwap: {} nodeStatusReportFrequency: 10s nodeStatusUpdateFrequency: 10s rotateCertificates: true runtimeRequestTimeout: 2m0s shutdownGracePeriod: 0s shutdownGracePeriodCriticalPods: 0s staticPodPath: /etc/kubernetes/manifests streamingConnectionIdleTimeout: 4h0m0s syncFrequency: 1m0s volumeStatsAggPeriod: 1m0s --- apiVersion: apps/v1 kind: DaemonSet metadata: name: kube-proxy namespace: kube-system labels: k8s-app: kube-proxy spec: selector: matchLabels: k8s-app: kube-proxy template: metadata: labels: k8s-app: kube-proxy spec: containers: - name: kube-proxy image: k8s.gcr.io/kube-proxy:v1.28.0 command: - /usr/local/bin/kube-proxy - --config=/var/lib/kube-proxy/config.conf - --hostname-override=$(NODE_NAME) env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName securityContext: privileged: true volumeMounts: - mountPath: /var/lib/kube-proxy name: kube-proxy - mountPath: /run/xtables.lock name: xtables-lock - mountPath: /lib/modules name: lib-modules readOnly: true hostNetwork: true nodeSelector: kubernetes.io/os: linux priorityClassName: system-node-critical serviceAccountName: kube-proxy tolerations: - key: CriticalAddonsOnly operator: Exists - operator: Exists volumes: - configMap: name: kube-proxy name: kube-proxy - hostPath: path: /run/xtables.lock type: FileOrCreate name: xtables-lock - hostPath: path: /lib/modules name: lib-modules --- apiVersion: v1 kind: ConfigMap metadata: name: kube-proxy namespace: kube-system data: config.conf: | apiVersion: kubeproxy.config.k8s.io/v1alpha1 bindAddress: 0.0.0.0 clientConnection: acceptContentTypes: "" burst: 10 contentType: application/vnd.kubernetes.protobuf kubeconfig: /var/lib/kube-proxy/kubeconfig.conf qps: 5 clusterCIDR: 10.244.0.0/16 configSyncPeriod: 15m0s conntrack: maxPerCore: 32768 min: 131072 tcpCloseWaitTimeout: 1h0m0s tcpEstablishedTimeout: 24h0m0s enableProfiling: false healthzBindAddress: 0.0.0.0:10256 hostnameOverride: "" iptables: masqueradeAll: false masqueradeBit: 14 minSyncPeriod: 0s syncPeriod: 30s ipvs: excludeCIDRs: null minSyncPeriod: 0s scheduler: "" strictARP: false syncPeriod: 30s tcpFinTimeout: 0s tcpTimeout: 0s udpTimeout: 0s kind: KubeProxyConfiguration metricsBindAddress: 127.0.0.1:10249 mode: "" nodePortAddresses: null oomScoreAdj: -999 portRange: "" showHiddenMetricsForVersion: "" udpIdleTimeout: 250ms winkernel: enableDSR: false networkName: "" sourceVip: "" kubeconfig.conf: | apiVersion: v1 kind: Config clusters: - cluster: certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt server: https://192.168.1.100:6443 name: default contexts: - context: cluster: default namespace: default user: default name: default current-context: default users: - name: default user: tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
2. 工作负载管理 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 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 apiVersion: apps/v1 kind: Deployment metadata: name: web-app namespace: production labels: app: web-app version: v1.0.0 environment: production spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 1 selector: matchLabels: app: web-app template: metadata: labels: app: web-app version: v1.0.0 annotations: prometheus.io/scrape: "true" prometheus.io/port: "8080" prometheus.io/path: "/metrics" spec: serviceAccountName: web-app securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 2000 containers: - name: web-app image: myregistry.com/web-app:v1.0.0 imagePullPolicy: Always ports: - name: http containerPort: 8080 protocol: TCP - name: metrics containerPort: 9090 protocol: TCP env: - name: NODE_ENV value: "production" - name: PORT value: "8080" - name: DATABASE_URL valueFrom: secretKeyRef: name: web-app-secrets key: database-url - name: REDIS_URL valueFrom: configMapKeyRef: name: web-app-config key: redis-url - name: LOG_LEVEL valueFrom: configMapKeyRef: name: web-app-config key: log-level resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" livenessProbe: httpGet: path: /health port: http initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: httpGet: path: /ready port: http initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 3 startupProbe: httpGet: path: /startup port: http initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 30 volumeMounts: - name: config-volume mountPath: /app/config readOnly: true - name: logs-volume mountPath: /app/logs - name: tmp-volume mountPath: /tmp securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL - name: sidecar-proxy image: envoyproxy/envoy:v1.27.0 ports: - name: proxy containerPort: 15001 resources: requests: memory: "64Mi" cpu: "50m" limits: memory: "128Mi" cpu: "100m" volumeMounts: - name: envoy-config mountPath: /etc/envoy volumes: - name: config-volume configMap: name: web-app-config - name: logs-volume emptyDir: {} - name: tmp-volume emptyDir: {} - name: envoy-config configMap: name: envoy-config imagePullSecrets: - name: registry-secret nodeSelector: node-type: application tolerations: - key: "application-only" operator: "Equal" value: "true" effect: "NoSchedule" affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - web-app topologyKey: kubernetes.io/hostname --- apiVersion: v1 kind: Service metadata: name: web-app-service namespace: production labels: app: web-app spec: type: ClusterIP ports: - name: http port: 80 targetPort: http protocol: TCP - name: metrics port: 9090 targetPort: metrics protocol: TCP selector: app: web-app --- apiVersion: v1 kind: ConfigMap metadata: name: web-app-config namespace: production data: redis-url: "redis://redis-service:6379" log-level: "info" max-connections: "100" timeout: "30s" app.properties: | server.port=8080 spring.profiles.active=production logging.level.com.example=INFO management.endpoints.web.exposure.include=health,info,metrics --- apiVersion: v1 kind: Secret metadata: name: web-app-secrets namespace: production type: Opaque data: database-url: cG9zdGdyZXNxbDovL3VzZXI6cGFzc3dvcmRAcG9zdGdyZXM6NTQzMi9teWRi api-key: YWJjZGVmZ2hpams= jwt-secret: c3VwZXJzZWNyZXRrZXk= --- apiVersion: v1 kind: ServiceAccount metadata: name: web-app namespace: production automountServiceAccountToken: true
StatefulSet有状态应用 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 apiVersion: apps/v1 kind: StatefulSet metadata: name: postgresql namespace: database labels: app: postgresql spec: serviceName: postgresql-headless replicas: 3 selector: matchLabels: app: postgresql template: metadata: labels: app: postgresql spec: serviceAccountName: postgresql securityContext: fsGroup: 999 containers: - name: postgresql image: postgres:15.4 ports: - name: postgresql containerPort: 5432 env: - name: POSTGRES_DB value: "myapp" - name: POSTGRES_USER valueFrom: secretKeyRef: name: postgresql-secret key: username - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: postgresql-secret key: password - name: POSTGRES_REPLICATION_USER value: "replicator" - name: POSTGRES_REPLICATION_PASSWORD valueFrom: secretKeyRef: name: postgresql-secret key: replication-password - name: PGDATA value: "/var/lib/postgresql/data/pgdata" resources: requests: memory: "1Gi" cpu: "500m" limits: memory: "2Gi" cpu: "1000m" livenessProbe: exec: command: - /bin/sh - -c - exec pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" -h 127.0 .0 .1 -p 5432 initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 6 readinessProbe: exec: command: - /bin/sh - -c - -e - | exec pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" -h 127.0.0.1 -p 5432 [ -f /opt/bitnami/postgresql/tmp/.initialized ] || [ -f /bitnami/postgresql/.initialized ] initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 6 volumeMounts: - name: postgresql-data mountPath: /var/lib/postgresql/data - name: postgresql-config mountPath: /etc/postgresql/postgresql.conf subPath: postgresql.conf - name: postgresql-init mountPath: /docker-entrypoint-initdb.d - name: postgres-exporter image: prometheuscommunity/postgres-exporter:v0.13.2 ports: - name: metrics containerPort: 9187 env: - name: DATA_SOURCE_NAME value: "postgresql://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@localhost:5432/$(POSTGRES_DB)?sslmode=disable" - name: POSTGRES_USER valueFrom: secretKeyRef: name: postgresql-secret key: username - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: postgresql-secret key: password - name: POSTGRES_DB value: "myapp" resources: requests: memory: "64Mi" cpu: "50m" limits: memory: "128Mi" cpu: "100m" volumes: - name: postgresql-config configMap: name: postgresql-config - name: postgresql-init configMap: name: postgresql-init volumeClaimTemplates: - metadata: name: postgresql-data spec: accessModes: ["ReadWriteOnce" ] storageClassName: "fast-ssd" resources: requests: storage: 20Gi --- apiVersion: v1 kind: Service metadata: name: postgresql-headless namespace: database labels: app: postgresql spec: type: ClusterIP clusterIP: None ports: - name: postgresql port: 5432 targetPort: postgresql - name: metrics port: 9187 targetPort: metrics selector: app: postgresql --- apiVersion: v1 kind: Service metadata: name: postgresql namespace: database labels: app: postgresql spec: type: ClusterIP ports: - name: postgresql port: 5432 targetPort: postgresql selector: app: postgresql --- apiVersion: v1 kind: ConfigMap metadata: name: postgresql-config namespace: database data: postgresql.conf: | # PostgreSQL configuration listen_addresses = '*' port = 5432 max_connections = 200 shared_buffers = 256MB effective_cache_size = 1GB maintenance_work_mem = 64MB checkpoint_completion_target = 0.9 wal_buffers = 16MB default_statistics_target = 100 random_page_cost = 1.1 effective_io_concurrency = 200 work_mem = 4MB min_wal_size = 1GB max_wal_size = 4GB log_destination = 'stderr' logging_collector = on log_directory = 'log' log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' log_statement = 'all' log_min_duration_statement = 1000 wal_level = replica max_wal_senders = 3 max_replication_slots = 3 hot_standby = on --- apiVersion: v1 kind: ConfigMap metadata: name: postgresql-init namespace: database data: 01-init-db.sql: | -- Create application database CREATE DATABASE myapp_production; -- Create application user CREATE USER app_user WITH PASSWORD 'app_password' ; GRANT ALL PRIVILEGES ON DATABASE myapp_production TO app_user; -- Create monitoring user CREATE USER monitoring WITH PASSWORD 'monitoring_password' ; GRANT SELECT ON ALL TABLES IN SCHEMA public TO monitoring; GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO monitoring; GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO monitoring; --- apiVersion: v1 kind: Secret metadata: name: postgresql-secret namespace: database type: Opaque data: username: cG9zdGdyZXM= password: cGFzc3dvcmQ= replication-password: cmVwbGljYXRvcg==
DaemonSet系统服务 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 apiVersion: apps/v1 kind: DaemonSet metadata: name: node-exporter namespace: monitoring labels: app: node-exporter spec: selector: matchLabels: app: node-exporter template: metadata: labels: app: node-exporter annotations: prometheus.io/scrape: "true" prometheus.io/port: "9100" spec: serviceAccountName: node-exporter securityContext: runAsNonRoot: true runAsUser: 65534 hostNetwork: true hostPID: true containers: - name: node-exporter image: prom/node-exporter:v1.6.1 args: - --path.procfs=/host/proc - --path.sysfs=/host/sys - --path.rootfs=/host/root - --collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/) - --collector.systemd - --collector.processes ports: - name: metrics containerPort: 9100 hostPort: 9100 resources: requests: memory: "64Mi" cpu: "50m" limits: memory: "128Mi" cpu: "100m" volumeMounts: - name: proc mountPath: /host/proc readOnly: true - name: sys mountPath: /host/sys readOnly: true - name: root mountPath: /host/root mountPropagation: HostToContainer readOnly: true securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL volumes: - name: proc hostPath: path: /proc - name: sys hostPath: path: /sys - name: root hostPath: path: / tolerations: - operator: Exists effect: NoSchedule - operator: Exists effect: NoExecute --- apiVersion: apps/v1 kind: DaemonSet metadata: name: fluent-bit namespace: logging labels: app: fluent-bit spec: selector: matchLabels: app: fluent-bit template: metadata: labels: app: fluent-bit spec: serviceAccountName: fluent-bit containers: - name: fluent-bit image: fluent/fluent-bit:2.1.8 ports: - name: http containerPort: 2020 env: - name: FLUENT_CONF value: fluent-bit.conf - name: FLUENT_OPT value: "" resources: requests: memory: "64Mi" cpu: "50m" limits: memory: "128Mi" cpu: "100m" volumeMounts: - name: fluent-bit-config mountPath: /fluent-bit/etc/ - name: varlog mountPath: /var/log readOnly: true - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true - name: etcmachineid mountPath: /etc/machine-id readOnly: true securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL volumes: - name: fluent-bit-config configMap: name: fluent-bit-config - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers - name: etcmachineid hostPath: path: /etc/machine-id type: File tolerations: - operator: Exists effect: NoSchedule - operator: Exists effect: NoExecute --- apiVersion: v1 kind: ConfigMap metadata: name: fluent-bit-config namespace: logging data: fluent-bit.conf: | [SERVICE] Flush 1 Log_Level info Daemon off Parsers_File parsers.conf HTTP_Server On HTTP_Listen 0.0.0.0 HTTP_Port 2020 [INPUT ] Name tail Path /var/log/containers/*.log Parser docker Tag kube.* Refresh_Interval 5 Mem_Buf_Limit 50MB Skip_Long_Lines On [INPUT ] Name systemd Tag host.* Systemd_Filter _SYSTEMD_UNIT=kubelet.service Read_From_Tail On [FILTER ] Name kubernetes Match kube.* Kube_URL https://kubernetes.default.svc:443 Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token Kube_Tag_Prefix kube.var.log.containers. Merge_Log On Keep_Log Off K8S-Logging.Parser On K8S-Logging.Exclude Off [OUTPUT ] Name es Match * Host elasticsearch.logging.svc.cluster.local Port 9200 Index fluent-bit Type _doc parsers.conf: | [PARSER] Name docker Format json Time_Key time Time_Format %Y-%m-%dT%H:%M:%S.%L Time_Keep On
3. 网络配置与服务发现 Ingress网络入口 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app-ingress namespace: production annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" nginx.ingress.kubernetes.io/rewrite-target: /$2 nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rate-limit: "100" nginx.ingress.kubernetes.io/rate-limit-window: "1m" nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/cors-allow-origin: "https://myapp.com" nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS" nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: tls: - hosts: - api.myapp.com - admin.myapp.com secretName: myapp-tls rules: - host: api.myapp.com http: paths: - path: /api/v1/users(/|$)(.*) pathType: Prefix backend: service: name: user-service port: number: 80 - path: /api/v1/orders(/|$)(.*) pathType: Prefix backend: service: name: order-service port: number: 80 - path: /api/v1/products(/|$)(.*) pathType: Prefix backend: service: name: product-service port: number: 80 - path: /api/v1/payments(/|$)(.*) pathType: Prefix backend: service: name: payment-service port: number: 80 - host: admin.myapp.com http: paths: - path: / pathType: Prefix backend: service: name: admin-frontend port: number: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-ingress-controller namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx spec: type: LoadBalancer ports: - name: http port: 80 targetPort: 80 protocol: TCP - name: https port: 443 targetPort: 443 protocol: TCP selector: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/component: controller
NetworkPolicy网络策略 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: web-app-network-policy namespace: production spec: podSelector: matchLabels: app: web-app policyTypes: - Ingress - Egress ingress: - from: - namespaceSelector: matchLabels: name: ingress-nginx - podSelector: matchLabels: app: api-gateway ports: - protocol: TCP port: 8080 - from: - namespaceSelector: matchLabels: name: monitoring podSelector: matchLabels: app: prometheus ports: - protocol: TCP port: 9090 egress: - to: - namespaceSelector: matchLabels: name: database podSelector: matchLabels: app: postgresql ports: - protocol: TCP port: 5432 - to: - namespaceSelector: matchLabels: name: cache podSelector: matchLabels: app: redis ports: - protocol: TCP port: 6379 - to: [] ports: - protocol: TCP port: 53 - protocol: UDP port: 53 --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: database-network-policy namespace: database spec: podSelector: matchLabels: app: postgresql policyTypes: - Ingress - Egress ingress: - from: - namespaceSelector: matchLabels: name: production - namespaceSelector: matchLabels: name: staging ports: - protocol: TCP port: 5432 - from: - namespaceSelector: matchLabels: name: monitoring podSelector: matchLabels: app: prometheus ports: - protocol: TCP port: 9187 egress: - to: [] ports: - protocol: TCP port: 53 - protocol: UDP port: 53 --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-default namespace: production spec: podSelector: {} policyTypes: - Ingress - Egress
Service Mesh配置 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: myapp-gateway namespace: production spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - api.myapp.com tls: httpsRedirect: true - port: number: 443 name: https protocol: HTTPS tls: mode: SIMPLE credentialName: myapp-tls hosts: - api.myapp.com --- apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: myapp-virtualservice namespace: production spec: hosts: - api.myapp.com gateways: - myapp-gateway http: - match: - uri: prefix: /api/v1/users route: - destination: host: user-service port: number: 80 fault: delay: percentage: value: 0.1 fixedDelay: 5s retries: attempts: 3 perTryTimeout: 2s - match: - uri: prefix: /api/v1/orders route: - destination: host: order-service port: number: 80 subset: v1 weight: 90 - destination: host: order-service port: number: 80 subset: v2 weight: 10 timeout: 10s --- apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: order-service-destination namespace: production spec: host: order-service trafficPolicy: connectionPool: tcp: maxConnections: 100 http: http1MaxPendingRequests: 50 maxRequestsPerConnection: 10 loadBalancer: simple: LEAST_CONN outlierDetection: consecutiveErrors: 3 interval: 30s baseEjectionTime: 30s maxEjectionPercent: 50 subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 --- apiVersion: security.istio.io/v1beta1 kind: PeerAuthentication metadata: name: default namespace: production spec: mtls: mode: STRICT --- apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: web-app-authz namespace: production spec: selector: matchLabels: app: web-app rules: - from: - source: principals: ["cluster.local/ns/production/sa/api-gateway" ] - to: - operation: methods: ["GET" , "POST" ] when: - key: request.headers[authorization] values: ["Bearer *" ]
4. 存储管理 持久化存储配置 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 78 79 80 81 82 apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast-ssd annotations: storageclass.kubernetes.io/is-default-class: "false" provisioner: kubernetes.io/aws-ebs parameters: type: gp3 iops: "3000" throughput: "125" encrypted: "true" allowVolumeExpansion: true volumeBindingMode: WaitForFirstConsumer reclaimPolicy: Delete --- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: standard-hdd provisioner: kubernetes.io/aws-ebs parameters: type: gp2 encrypted: "true" allowVolumeExpansion: true volumeBindingMode: Immediate reclaimPolicy: Retain --- apiVersion: v1 kind: PersistentVolume metadata: name: nfs-pv labels: type: nfs spec: capacity: storage: 100Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: server: nfs-server.example.com path: /shared/data mountOptions: - nfsvers=4.1 - rsize=1048576 - wsize=1048576 - hard - intr - timeo=600 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: web-app-storage namespace: production spec: accessModes: - ReadWriteOnce storageClassName: fast-ssd resources: requests: storage: 20Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: shared-storage namespace: production spec: accessModes: - ReadWriteMany storageClassName: nfs resources: requests: storage: 50Gi
备份与恢复 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 apiVersion: batch/v1 kind: CronJob metadata: name: database-backup namespace: database spec: schedule: "0 2 * * *" jobTemplate: spec: template: spec: serviceAccountName: backup-service containers: - name: postgres-backup image: postgres:15.4 command: - /bin/bash - -c - | BACKUP_FILE="/backup/postgres-$(date +%Y%m%d-%H%M%S).sql" pg_dump -h postgresql -U $POSTGRES_USER -d $POSTGRES_DB > $BACKUP_FILE gzip $BACKUP_FILE aws s3 cp ${BACKUP_FILE}.gz s3://myapp-backups/database/ find /backup -name "postgres-*.sql.gz" -mtime +7 -delete echo "Backup completed: ${BACKUP_FILE}.gz" env: - name: POSTGRES_USER valueFrom: secretKeyRef: name: postgresql-secret key: username - name: POSTGRES_DB value: "myapp" - name: PGPASSWORD valueFrom: secretKeyRef: name: postgresql-secret key: password - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: name: aws-credentials key: access-key-id - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: aws-credentials key: secret-access-key volumeMounts: - name: backup-storage mountPath: /backup volumes: - name: backup-storage persistentVolumeClaim: claimName: backup-storage restartPolicy: OnFailure successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 1 --- apiVersion: batch/v1 kind: Job metadata: name: database-restore namespace: database spec: template: spec: serviceAccountName: backup-service containers: - name: postgres-restore image: postgres:15.4 command: - /bin/bash - -c - | # Download backup from S3 aws s3 cp s3://myapp-backups/database/$BACKUP_FILE /tmp/ gunzip -c /tmp/$BACKUP_FILE | psql -h postgresql -U $POSTGRES_USER -d $POSTGRES_DB echo "Restore completed from: $BACKUP_FILE" env: - name: BACKUP_FILE value: "postgres-20240315-020000.sql.gz" - name: POSTGRES_USER valueFrom: secretKeyRef: name: postgresql-secret key: username - name: POSTGRES_DB value: "myapp" - name: PGPASSWORD valueFrom: secretKeyRef: name: postgresql-secret key: password - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: name: aws-credentials key: access-key-id - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: aws-credentials key: secret-access-key restartPolicy: Never backoffLimit: 3
5. 自动扩缩容 HPA水平扩缩容 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: web-app-hpa namespace: production spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: web-app minReplicas: 3 maxReplicas: 50 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 - type: Resource resource: name: memory target: type: Utilization averageUtilization: 80 - type: Pods pods: metric: name: http_requests_per_second target: type: AverageValue averageValue: "100" - type: External external: metric: name: sqs_queue_length selector: matchLabels: queue: "web-app-queue" target: type: Value value: "10" behavior: scaleDown: stabilizationWindowSeconds: 300 policies: - type: Percent value: 10 periodSeconds: 60 - type: Pods value: 2 periodSeconds: 60 selectPolicy: Min scaleUp: stabilizationWindowSeconds: 60 policies: - type: Percent value: 50 periodSeconds: 60 - type: Pods value: 5 periodSeconds: 60 selectPolicy: Max --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: order-service-hpa namespace: production spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: order-service minReplicas: 2 maxReplicas: 20 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 60 - type: Object object: metric: name: requests_per_second describedObject: apiVersion: networking.istio.io/v1beta1 kind: VirtualService name: order-service target: type: Value value: "50" behavior: scaleDown: stabilizationWindowSeconds: 600 policies: - type: Percent value: 25 periodSeconds: 120 scaleUp: stabilizationWindowSeconds: 120 policies: - type: Percent value: 100 periodSeconds: 60
VPA垂直扩缩容 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 apiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: web-app-vpa namespace: production spec: targetRef: apiVersion: apps/v1 kind: Deployment name: web-app updatePolicy: updateMode: "Auto" resourcePolicy: containerPolicies: - containerName: web-app minAllowed: cpu: 100m memory: 128Mi maxAllowed: cpu: 2000m memory: 2Gi controlledResources: ["cpu" , "memory" ] controlledValues: RequestsAndLimits - containerName: sidecar-proxy minAllowed: cpu: 50m memory: 64Mi maxAllowed: cpu: 200m memory: 256Mi controlledResources: ["cpu" , "memory" ] --- apiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: database-vpa namespace: database spec: targetRef: apiVersion: apps/v1 kind: StatefulSet name: postgresql updatePolicy: updateMode: "Off" resourcePolicy: containerPolicies: - containerName: postgresql minAllowed: cpu: 500m memory: 1Gi maxAllowed: cpu: 4000m memory: 8Gi controlledResources: ["cpu" , "memory" ]
集群自动扩缩容 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 apiVersion: apps/v1 kind: Deployment metadata: name: cluster-autoscaler namespace: kube-system labels: app: cluster-autoscaler spec: selector: matchLabels: app: cluster-autoscaler template: metadata: labels: app: cluster-autoscaler annotations: prometheus.io/scrape: 'true' prometheus.io/port: '8085' spec: serviceAccountName: cluster-autoscaler containers: - image: k8s.gcr.io/autoscaling/cluster-autoscaler:v1.27.3 name: cluster-autoscaler resources: limits: cpu: 100m memory: 300Mi requests: cpu: 100m memory: 300Mi command: - ./cluster-autoscaler - --v=4 - --stderrthreshold=info - --cloud-provider=aws - --skip-nodes-with-local-storage=false - --expander=least-waste - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/myapp-cluster - --balance-similar-node-groups - --scale-down-enabled=true - --scale-down-delay-after-add=10m - --scale-down-unneeded-time=10m - --scale-down-utilization-threshold=0.5 - --max-node-provision-time=15m - --max-empty-bulk-delete=10 - --max-graceful-termination-sec=600 env: - name: AWS_REGION value: us-west-2 volumeMounts: - name: ssl-certs mountPath: /etc/ssl/certs/ca-certificates.crt readOnly: true imagePullPolicy: "Always" volumes: - name: ssl-certs hostPath: path: "/etc/ssl/certs/ca-bundle.crt" --- apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler name: cluster-autoscaler namespace: kube-system automountServiceAccountToken: true --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cluster-autoscaler labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler rules: - apiGroups: ["" ] resources: ["events" , "endpoints" ] verbs: ["create" , "patch" ] - apiGroups: ["" ] resources: ["pods/eviction" ] verbs: ["create" ] - apiGroups: ["" ] resources: ["pods/status" ] verbs: ["update" ] - apiGroups: ["" ] resources: ["endpoints" ] resourceNames: ["cluster-autoscaler" ] verbs: ["get" , "update" ] - apiGroups: ["" ] resources: ["nodes" ] verbs: ["watch" , "list" , "get" , "update" ] - apiGroups: ["" ] resources: ["pods" , "services" , "replicationcontrollers" , "persistentvolumeclaims" , "persistentvolumes" ] verbs: ["watch" , "list" , "get" ] - apiGroups: ["extensions" ] resources: ["replicasets" , "daemonsets" ] verbs: ["watch" , "list" , "get" ] - apiGroups: ["policy" ] resources: ["poddisruptionbudgets" ] verbs: ["watch" , "list" ] - apiGroups: ["apps" ] resources: ["statefulsets" , "replicasets" , "daemonsets" ] verbs: ["watch" , "list" , "get" ] - apiGroups: ["storage.k8s.io" ] resources: ["storageclasses" , "csinodes" , "csidrivers" , "csistoragecapacities" ] verbs: ["watch" , "list" , "get" ] - apiGroups: ["batch" , "extensions" ] resources: ["jobs" ] verbs: ["get" , "list" , "watch" , "patch" ] - apiGroups: ["coordination.k8s.io" ] resources: ["leases" ] verbs: ["create" ] - apiGroups: ["coordination.k8s.io" ] resourceNames: ["cluster-autoscaler" ] resources: ["leases" ] verbs: ["get" , "update" ] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: cluster-autoscaler labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-autoscaler subjects: - kind: ServiceAccount name: cluster-autoscaler namespace: kube-system
6. 监控与日志 Prometheus监控配置 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 apiVersion: v1 kind: ConfigMap metadata: name: prometheus-config namespace: monitoring data: prometheus.yml: | global: scrape_interval: 15s evaluation_interval: 15s external_labels: cluster: 'myapp-cluster' region: 'us-west-2' rule_files: - "/etc/prometheus/rules/*.yml" alerting: alertmanagers: - static_configs: - targets: - alertmanager:9093 scrape_configs: - job_name: 'kubernetes-apiservers' kubernetes_sd_configs: - role: endpoints scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token relabel_configs: - source_labels: [__meta_kubernetes_namespace , __meta_kubernetes_service_name , __meta_kubernetes_endpoint_port_name ] action: keep regex: default;kubernetes;https - job_name: 'kubernetes-nodes' kubernetes_sd_configs: - role: node scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+) - target_label: __address__ replacement: kubernetes.default.svc:443 - source_labels: [__meta_kubernetes_node_name ] regex: (.+) target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape ] action: keep regex: true - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path ] action: replace target_label: __metrics_path__ regex: (.+) - source_labels: [__address__ , __meta_kubernetes_pod_annotation_prometheus_io_port ] action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 target_label: __address__ - action: labelmap regex: __meta_kubernetes_pod_label_(.+) - source_labels: [__meta_kubernetes_namespace ] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_pod_name ] action: replace target_label: kubernetes_pod_name - job_name: 'kubernetes-services' kubernetes_sd_configs: - role: endpoints relabel_configs: - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape ] action: keep regex: true - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme ] action: replace target_label: __scheme__ regex: (https?) - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path ] action: replace target_label: __metrics_path__ regex: (.+) - source_labels: [__address__ , __meta_kubernetes_service_annotation_prometheus_io_port ] action: replace target_label: __address__ regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 - action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: [__meta_kubernetes_namespace ] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name ] action: replace target_label: kubernetes_name alerts.yml: | groups: - name: kubernetes-alerts rules: - alert: KubernetesPodCrashLooping expr: rate(kube_pod_container_status_restarts_total[15m]) > 0 for: 5m labels: severity: warning annotations: summary: "Pod {{ $labels.pod }} is crash looping" description: "Pod {{ $labels.pod }} in namespace {{ $labels.namespace }} is restarting frequently" - alert: KubernetesNodeNotReady expr: kube_node_status_condition{condition="Ready",status="true"} == 0 for: 5m labels: severity: critical annotations: summary: "Node {{ $labels.node }} is not ready" description: "Node {{ $labels.node }} has been not ready for more than 5 minutes" - alert: KubernetesPodNotReady expr: kube_pod_status_phase{phase=~"Pending|Unknown"} > 0 for: 10m labels: severity: warning annotations: summary: "Pod {{ $labels.pod }} not ready" description: "Pod {{ $labels.pod }} in namespace {{ $labels.namespace }} has been in {{ $labels.phase }} state for more than 10 minutes" - alert: KubernetesHighCPUUsage expr: (sum by (instance) (rate(container_cpu_usage_seconds_total[5m])) * 100 ) > 80 for: 10m labels: severity: warning annotations: summary: "High CPU usage on {{ $labels.instance }} " description: "CPU usage is above 80% on {{ $labels.instance }} for more than 10 minutes" - alert: KubernetesHighMemoryUsage expr: (sum by (instance) (container_memory_working_set_bytes) / sum by (instance) (machine_memory_bytes) * 100 ) > 85 for: 10m labels: severity: warning annotations: summary: "High memory usage on {{ $labels.instance }} " description: "Memory usage is above 85% on {{ $labels.instance }} for more than 10 minutes" --- apiVersion: apps/v1 kind: Deployment metadata: name: prometheus namespace: monitoring labels: app: prometheus spec: replicas: 1 selector: matchLabels: app: prometheus template: metadata: labels: app: prometheus spec: serviceAccountName: prometheus containers: - name: prometheus image: prom/prometheus:v2.45.0 args: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus/' - '--web.console.libraries=/etc/prometheus/console_libraries' - '--web.console.templates=/etc/prometheus/consoles' - '--storage.tsdb.retention.time=30d' - '--web.enable-lifecycle' - '--web.enable-admin-api' ports: - containerPort: 9090 resources: requests: memory: "2Gi" cpu: "500m" limits: memory: "4Gi" cpu: "1000m" volumeMounts: - name: prometheus-config mountPath: /etc/prometheus/ - name: prometheus-storage mountPath: /prometheus/ livenessProbe: httpGet: path: /-/healthy port: 9090 initialDelaySeconds: 30 timeoutSeconds: 30 readinessProbe: httpGet: path: /-/ready port: 9090 initialDelaySeconds: 30 timeoutSeconds: 30 volumes: - name: prometheus-config configMap: name: prometheus-config - name: prometheus-storage persistentVolumeClaim: claimName: prometheus-storage --- apiVersion: v1 kind: Service metadata: name: prometheus namespace: monitoring labels: app: prometheus spec: ports: - port: 9090 targetPort: 9090 selector: app: prometheus
Grafana可视化配置 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 apiVersion: apps/v1 kind: Deployment metadata: name: grafana namespace: monitoring labels: app: grafana spec: replicas: 1 selector: matchLabels: app: grafana template: metadata: labels: app: grafana spec: serviceAccountName: grafana containers: - name: grafana image: grafana/grafana:10.0.3 ports: - containerPort: 3000 env: - name: GF_SECURITY_ADMIN_PASSWORD valueFrom: secretKeyRef: name: grafana-secret key: admin-password - name: GF_INSTALL_PLUGINS value: "grafana-kubernetes-app,grafana-piechart-panel,grafana-worldmap-panel" resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" cpu: "200m" volumeMounts: - name: grafana-storage mountPath: /var/lib/grafana - name: grafana-config mountPath: /etc/grafana/grafana.ini subPath: grafana.ini - name: grafana-datasources mountPath: /etc/grafana/provisioning/datasources - name: grafana-dashboards-config mountPath: /etc/grafana/provisioning/dashboards - name: grafana-dashboards mountPath: /var/lib/grafana/dashboards livenessProbe: httpGet: path: /api/health port: 3000 initialDelaySeconds: 30 timeoutSeconds: 30 readinessProbe: httpGet: path: /api/health port: 3000 initialDelaySeconds: 5 timeoutSeconds: 10 volumes: - name: grafana-storage persistentVolumeClaim: claimName: grafana-storage - name: grafana-config configMap: name: grafana-config - name: grafana-datasources configMap: name: grafana-datasources - name: grafana-dashboards-config configMap: name: grafana-dashboards-config - name: grafana-dashboards configMap: name: grafana-dashboards --- apiVersion: v1 kind: ConfigMap metadata: name: grafana-config namespace: monitoring data: grafana.ini: | [analytics] check_for_updates = true [grafana_net ] url = https://grafana.net [log ] mode = console [paths ] data = /var/lib/grafana/data logs = /var/log/grafana plugins = /var/lib/grafana/plugins provisioning = /etc/grafana/provisioning [server ] root_url = https://grafana.myapp.com [security ] admin_user = admin cookie_secure = true [users ] allow_sign_up = false --- apiVersion: v1 kind: ConfigMap metadata: name: grafana-datasources namespace: monitoring data: datasources.yaml: | apiVersion: 1 datasources: - name: Prometheus type: prometheus access: proxy url: http://prometheus:9090 isDefault: true editable: true --- apiVersion: v1 kind: ConfigMap metadata: name: grafana-dashboards-config namespace: monitoring data: dashboards.yaml: | apiVersion: 1 providers: - name: 'default' orgId: 1 folder: '' type: file disableDeletion: false updateIntervalSeconds: 10 options: path: /var/lib/grafana/dashboards --- apiVersion: v1 kind: Service metadata: name: grafana namespace: monitoring labels: app: grafana spec: ports: - port: 3000 targetPort: 3000 selector: app: grafana
7. 安全配置 RBAC权限控制 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 apiVersion: v1 kind: ServiceAccount metadata: name: web-app-service-account namespace: production --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: production name: web-app-role rules: - apiGroups: ["" ] resources: ["configmaps" , "secrets" ] verbs: ["get" , "list" ] - apiGroups: ["" ] resources: ["pods" ] verbs: ["get" , "list" , "watch" ] - apiGroups: ["apps" ] resources: ["deployments" ] verbs: ["get" , "list" ] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: web-app-role-binding namespace: production subjects: - kind: ServiceAccount name: web-app-service-account namespace: production roleRef: kind: Role name: web-app-role apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: monitoring-cluster-role rules: - apiGroups: ["" ] resources: ["nodes" , "nodes/proxy" , "services" , "endpoints" , "pods" ] verbs: ["get" , "list" , "watch" ] - apiGroups: ["extensions" ] resources: ["ingresses" ] verbs: ["get" , "list" , "watch" ] - nonResourceURLs: ["/metrics" ] verbs: ["get" ] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: monitoring-cluster-role-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: monitoring-cluster-role subjects: - kind: ServiceAccount name: prometheus namespace: monitoring
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: restricted-psp spec: privileged: false allowPrivilegeEscalation: false requiredDropCapabilities: - ALL volumes: - 'configMap' - 'emptyDir' - 'projected' - 'secret' - 'downwardAPI' - 'persistentVolumeClaim' runAsUser: rule: 'MustRunAsNonRoot' seLinux: rule: 'RunAsAny' fsGroup: rule: 'RunAsAny' readOnlyRootFilesystem: true --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: restricted-psp-user rules: - apiGroups: ['policy' ] resources: ['podsecuritypolicies' ] verbs: ['use' ] resourceNames: - restricted-psp --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: restricted-psp-all-serviceaccounts roleRef: kind: ClusterRole name: restricted-psp-user apiGroup: rbac.authorization.k8s.io subjects: - kind: Group name: system:serviceaccounts apiGroup: rbac.authorization.k8s.io
网络安全策略 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 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-all namespace: production spec: podSelector: {} policyTypes: - Ingress - Egress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-web-app-ingress namespace: production spec: podSelector: matchLabels: app: web-app policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: name: ingress-nginx ports: - protocol: TCP port: 8080 --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-web-app-egress namespace: production spec: podSelector: matchLabels: app: web-app policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: name: database ports: - protocol: TCP port: 5432 - to: - namespaceSelector: matchLabels: name: cache ports: - protocol: TCP port: 6379 - to: [] ports: - protocol: TCP port: 53 - protocol: UDP port: 53 - protocol: TCP port: 443
8. 故障排查与运维 故障排查工具 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 #!/bin/bash check_cluster_health () { echo "=== 检查集群健康状态 ===" kubectl get nodes -o wide kubectl get componentstatuses kubectl top nodes echo -e "\n=== 检查系统Pod状态 ===" kubectl get pods -n kube-system echo -e "\n=== 检查关键服务状态 ===" kubectl get pods -n ingress-nginx kubectl get pods -n monitoring kubectl get pods -n logging } check_application_health () { local namespace=${1:-production} echo "=== 检查应用Pod状态 ($namespace ) ===" kubectl get pods -n $namespace -o wide kubectl get deployments -n $namespace kubectl get services -n $namespace echo -e "\n=== 检查Pod资源使用情况 ===" kubectl top pods -n $namespace echo -e "\n=== 检查HPA状态 ===" kubectl get hpa -n $namespace } check_network_connectivity () { local namespace=${1:-production} echo "=== 检查网络策略 ===" kubectl get networkpolicies -n $namespace echo -e "\n=== 检查Ingress配置 ===" kubectl get ingress -n $namespace -o wide kubectl describe ingress -n $namespace echo -e "\n=== 检查Service端点 ===" kubectl get endpoints -n $namespace } check_storage_status () { echo "=== 检查存储类 ===" kubectl get storageclass echo -e "\n=== 检查PV/PVC状态 ===" kubectl get pv kubectl get pvc --all-namespaces echo -e "\n=== 检查存储使用情况 ===" kubectl describe pv } collect_pod_logs () { local namespace=${1:-production} local pod_name=$2 local container_name=${3:-""} if [ -z "$pod_name " ]; then echo "请提供Pod名称" return 1 fi echo "=== 收集Pod日志: $pod_name ===" if [ -n "$container_name " ]; then kubectl logs -n $namespace $pod_name -c $container_name --tail =100 kubectl logs -n $namespace $pod_name -c $container_name --previous --tail =100 2>/dev/null else kubectl logs -n $namespace $pod_name --tail =100 kubectl logs -n $namespace $pod_name --previous --tail =100 2>/dev/null fi echo -e "\n=== Pod详细信息 ===" kubectl describe pod -n $namespace $pod_name echo -e "\n=== Pod事件 ===" kubectl get events -n $namespace --field-selector involvedObject.name=$pod_name } check_resource_quotas () { local namespace=${1:-production} echo "=== 检查资源配额 ($namespace ) ===" kubectl get resourcequota -n $namespace kubectl describe resourcequota -n $namespace echo -e "\n=== 检查限制范围 ===" kubectl get limitrange -n $namespace kubectl describe limitrange -n $namespace } performance_analysis () { local namespace=${1:-production} echo "=== 节点资源使用情况 ===" kubectl top nodes echo -e "\n=== Pod资源使用情况 ===" kubectl top pods -n $namespace --sort-by=cpu kubectl top pods -n $namespace --sort-by=memory echo -e "\n=== 检查资源请求和限制 ===" kubectl describe pods -n $namespace | grep -A 5 -B 5 "Requests\|Limits" } network_diagnosis () { local namespace=${1:-production} local pod_name=$2 if [ -z "$pod_name " ]; then echo "请提供Pod名称进行网络诊断" return 1 fi echo "=== 网络诊断: $pod_name ===" kubectl get pod -n $namespace $pod_name -o wide kubectl get endpoints -n $namespace echo -e "\n=== 执行网络连通性测试 ===" kubectl exec -n $namespace $pod_name -- nslookup kubernetes.default.svc.cluster.local kubectl exec -n $namespace $pod_name -- wget -qO- --timeout =5 http://kubernetes.default.svc.cluster.local/healthz } main () { case $1 in "cluster" ) check_cluster_health ;; "app" ) check_application_health $2 ;; "network" ) check_network_connectivity $2 ;; "storage" ) check_storage_status ;; "logs" ) collect_pod_logs $2 $3 $4 ;; "quota" ) check_resource_quotas $2 ;; "perf" ) performance_analysis $2 ;; "netdiag" ) network_diagnosis $2 $3 ;; *) echo "使用方法: $0 {cluster|app|network|storage|logs|quota|perf|netdiag} [namespace] [pod_name] [container_name]" echo "" echo "命令说明:" echo " cluster - 检查集群健康状态" echo " app - 检查应用状态 [namespace]" echo " network - 检查网络连通性 [namespace]" echo " storage - 检查存储状态" echo " logs - 收集Pod日志 [namespace] [pod_name] [container_name]" echo " quota - 检查资源配额 [namespace]" echo " perf - 性能分析 [namespace]" echo " netdiag - 网络诊断 [namespace] [pod_name]" ;; esac } main "$@ "
运维自动化脚本 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 #!/bin/bash rolling_update () { local namespace=$1 local deployment=$2 local image=$3 if [ -z "$namespace " ] || [ -z "$deployment " ] || [ -z "$image " ]; then echo "使用方法: rolling_update <namespace> <deployment> <image>" return 1 fi echo "开始滚动更新: $deployment -> $image " kubectl set image deployment/$deployment -n $namespace $deployment =$image kubectl rollout status deployment/$deployment -n $namespace --timeout =600s if [ $? -eq 0 ]; then echo "滚动更新成功完成" kubectl get pods -n $namespace -l app=$deployment else echo "滚动更新失败,开始回滚" kubectl rollout undo deployment/$deployment -n $namespace kubectl rollout status deployment/$deployment -n $namespace fi } scale_deployment () { local namespace=$1 local deployment=$2 local replicas=$3 if [ -z "$namespace " ] || [ -z "$deployment " ] || [ -z "$replicas " ]; then echo "使用方法: scale_deployment <namespace> <deployment> <replicas>" return 1 fi echo "扩缩容操作: $deployment -> $replicas 副本" kubectl scale deployment/$deployment -n $namespace --replicas=$replicas kubectl rollout status deployment/$deployment -n $namespace echo "扩缩容完成" kubectl get pods -n $namespace -l app=$deployment } backup_etcd () { local backup_dir=${1:-"/backup/etcd"} local etcd_endpoints=${2:-"https://127.0.0.1:2379"} echo "开始备份ETCD数据" mkdir -p $backup_dir ETCDCTL_API=3 etcdctl snapshot save $backup_dir /etcd-snapshot-$(date +%Y%m%d-%H%M%S).db \ --endpoints=$etcd_endpoints \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key if [ $? -eq 0 ]; then echo "ETCD备份成功: $backup_dir " ls -la $backup_dir / find $backup_dir -name "etcd-snapshot-*.db" -mtime +7 -delete else echo "ETCD备份失败" return 1 fi } restore_etcd () { local snapshot_file=$1 local data_dir=${2:-"/var/lib/etcd"} if [ -z "$snapshot_file " ]; then echo "使用方法: restore_etcd <snapshot_file> [data_dir]" return 1 fi if [ ! -f "$snapshot_file " ]; then echo "快照文件不存在: $snapshot_file " return 1 fi echo "开始恢复ETCD数据从: $snapshot_file " systemctl stop etcd mv $data_dir $data_dir .backup.$(date +%Y%m%d-%H%M%S) ETCDCTL_API=3 etcdctl snapshot restore $snapshot_file \ --data-dir=$data_dir \ --name=master \ --initial-cluster=master=https://127.0.0.1:2380 \ --initial-advertise-peer-urls=https://127.0.0.1:2380 chown -R etcd:etcd $data_dir systemctl start etcd echo "ETCD恢复完成" } cleanup_resources () { local namespace=${1:-"--all-namespaces"} echo "开始清理未使用的资源" kubectl delete jobs --field-selector status.successful=1 $namespace kubectl delete pods --field-selector status.phase=Failed $namespace kubectl delete pods --field-selector status.phase=Succeeded $namespace echo "检查未使用的ConfigMap和Secret(仅显示,不删除)" kubectl get configmaps $namespace --no-headers | while read name namespace; do if ! kubectl get pods $namespace -o yaml | grep -q $name ; then echo "未使用的ConfigMap: $name (namespace: $namespace )" fi done echo "资源清理完成" } update_certificates () { local cert_dir="/etc/kubernetes/pki" echo "开始更新Kubernetes证书" cp -r $cert_dir $cert_dir .backup.$(date +%Y%m%d-%H%M%S) kubeadm certs renew all systemctl restart kubelet kubeadm certs check-expiration echo "证书更新完成" } node_maintenance () { local node_name=$1 local action=$2 if [ -z "$node_name " ] || [ -z "$action " ]; then echo "使用方法: node_maintenance <node_name> <drain|uncordon>" return 1 fi case $action in "drain" ) echo "将节点 $node_name 设置为维护模式" kubectl cordon $node_name kubectl drain $node_name --ignore-daemonsets --delete-emptydir-data --force ;; "uncordon" ) echo "将节点 $node_name 恢复为可调度状态" kubectl uncordon $node_name ;; *) echo "无效的操作: $action " return 1 ;; esac kubectl get nodes } main () { case $1 in "update" ) rolling_update $2 $3 $4 ;; "scale" ) scale_deployment $2 $3 $4 ;; "backup-etcd" ) backup_etcd $2 $3 ;; "restore-etcd" ) restore_etcd $2 $3 ;; "cleanup" ) cleanup_resources $2 ;; "update-certs" ) update_certificates ;; "maintenance" ) node_maintenance $2 $3 ;; *) echo "使用方法: $0 {update|scale|backup-etcd|restore-etcd|cleanup|update-certs|maintenance} [参数...]" echo "" echo "命令说明:" echo " update - 滚动更新应用 <namespace> <deployment> <image>" echo " scale - 扩缩容操作 <namespace> <deployment> <replicas>" echo " backup-etcd - 备份ETCD [backup_dir] [endpoints]" echo " restore-etcd - 恢复ETCD <snapshot_file> [data_dir]" echo " cleanup - 清理未使用资源 [namespace]" echo " update-certs - 更新证书" echo " maintenance - 节点维护 <node_name> <drain|uncordon>" ;; esac } main "$@ "
总结 Kubernetes容器编排技术为现代应用提供了强大的部署和管理能力。通过本指南的学习,我们掌握了:
核心能力
集群架构理解 :深入了解控制平面和节点组件的工作原理
工作负载管理 :熟练使用Deployment、StatefulSet、DaemonSet等资源
网络配置 :掌握Service、Ingress、NetworkPolicy等网络组件
存储管理 :理解PV、PVC、StorageClass等存储概念
自动扩缩容 :实现HPA、VPA和集群自动扩缩容
监控运维 :建立完整的监控、日志和告警体系
最佳实践
安全优先 :实施RBAC、网络策略、Pod安全策略
资源优化 :合理配置资源请求和限制
高可用设计 :多副本部署、反亲和性配置
故障恢复 :定期备份、快速恢复机制
持续改进 :监控指标分析、性能优化
发展方向
云原生生态 :与Istio、Knative等项目集成
边缘计算 :K3s、KubeEdge等轻量级解决方案
AI/ML工作负载 :Kubeflow、Seldon等机器学习平台
GitOps :ArgoCD、Flux等声明式部署
可观测性 :OpenTelemetry、Jaeger等分布式追踪
Kubernetes作为容器编排的标准平台,将继续推动云原生技术的发展,为企业数字化转型提供强有力的技术支撑。