Kubernetes 架构简介和概览
Docker 简介
什么是容器?
- 容器是一个软件的标准单元,其中打包了代码及其所有的依赖。
什么是 Docker?
- 一个容器管理系统
- 易于部署
- 独立实例
- 轻量
Docke Engine
- 作为守护进程运行的服务
- 有 Restful API
- 命令行界面(cli)
注:本文中采用 Ubuntu 16.04进行所有的安装及测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
apt-get update # 安装 apt-get install docker.io -y # 查看状态 systemctl status docker # 拉取镜像 docker pull nginx # 查看镜像 docker images # 运行容器 docker run -d -p 192.168.x.x:80:80 --name nginx-container nginx # 查看容器 docker ps # 或 docker container ls # 进入容器 docker exec -it nginx-container /bin/bash |
Kubernetes 集群架构概览
什么是 Kubernetes?
- 容器集群管理器
- 开源
- 灵活
单节点 Kubernetes 部署(Minikube)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
apt-get update apt-get install curl -y apt install virtualbox virtualbox-ext-pack mkdir /minikube && cd /minikube curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 chmod +x minikube mv -v minikube /usr/local/bin/ curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl chmod +x kubectl mv -v kubectl /usr/local/bin # 启动服务 minikube start # 虚拟机中可以使用minikube start --vm-driver=none # 检查minikube 所安装的服务 kubectl get pods --all-namespaces |
掌握 YAML文件
什么是 YAML?
- 标记语言
- 易于阅读
两个 Kubernetes 对象字段:
- Spec 对象
- Status 对象
1 2 3 4 5 6 7 8 9 10 |
apiVersion: v1 kind: Deployment metadata: name: nginx-dev spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 |
常用 Kubernetes对象:
- Nodes
- Pods
- Deployments
- Services
- ConfigMaps
构建第一个 Pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# vi nginx.yaml apiVersion: v1 # for versions before 1.9.0 use apps/v1beta2 kind: Pod metadata: name: nginx-deployment spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 # 创建 kubectl create -f nginx.yaml # 查看 kubectl get pods |
配置 Kubernetes 集群
规划Kubernetes 集群
为什么要设计 Kubernetes集群?
- 通过构建集群来启动团队自治
- 以花费较少的方式进行伸缩
设计 Kubernetes 集群
- Labels:组织服务
- RBAC:Role-Based Access Control
- 命名空间管理员:管理命名空间中的所有内容
- 命名空间部署负责人:允许使用”get”, “list”, “watch”, “create”, “update”, “patch”和”delete”
- 集群读用户:允许使用”get”, “list”和”watch”
- 命名空间
- 资源配额
- 自动伸缩
- Helm:包管理器
环境设置概览
安装 Kubernetes 的步骤:
- 在所有节点上安装 Docker
- 添加仓库密钥
- 下载 Kubernetes 二进制文件
- 添加仓库源
- 更新系统
- 安装工具:kubeadm kubelet kubectl
- kubeadm init
- 添加工作节点的密钥
- 对用户应用权限
- 配置 CNI(容器网络接口),有 flannel、Contiv 和 Weave
需开启的端口(如开启了防火墙):
Kubernetes 集群安装
准备两台主机/虚拟机:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# 国内可替换镜像源 sudo sed -i "s/archive.ubuntu.com/mirrors.aliyun.com/g" /etc/apt/sources.list sudo sed -i "s/security.ubuntu.com/mirrors.aliyun.com/g" /etc/apt/sources.list # 安装 apt-get update && apt-get upgrade -y apt-get install docker.io -y curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - vi /etc/apt/sources.list.d/kubernetes.list deb https://apt.kubernetes.io/ kubernetes-xenial main apt-get update apt install -y kubelet kubeadm kubectl swapoff -a # master kubeadm init --pod-network-cidr=10.244.0.0/16 # 10.244.0.0/16为 flannel 配置的默认值 # 也可指定 IP:kubeadm init --apiserver-advertise-address=192.168.x.x --pod-network-cidr=10.244.0.0/16 # 出现错误可进行重置kubeadm reset |
根据提示分别在主节点上使用普通用户执行如下命令:
1 2 3 4 5 6 7 8 |
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config # 查看启动状况 kubectl get pods --all-namespaces # 启动 flannel kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml |
在 worker 节点的 root 用户下执行前面所提示的命令(请根据实际状况修改):
1 2 |
kubeadm join 192.168.50.143:6443 --token u12uxc.hae8535xmsue7w55 \ --discovery-token-ca-cert-hash sha256:ac7d6fe0371dd84d406f7378d5e0c6314611e6e48209bc6c480bf886b83466b4 |
若出现如下错误:
1 |
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/ |
可按照文档执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
cat > /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2" } EOF mkdir -p /etc/systemd/system/docker.service.d # Restart docker. systemctl daemon-reload systemctl restart docker |
注意:如果使用的镜像默认创建的主机名都相同,请在/etc/hostname 中进行修改
其它命令
1 2 |
# 创建打印 token kubeadm token create --print-join-command |
Kubernetes 服务验证
1 2 3 4 5 6 7 8 9 10 11 12 |
kubectl get pods --all-namespaces kubectl get nodes free -h cat /proc/swaps # 节点出现问题可查看日志 kubelet logs worker-node1 sudo journalctl -u kubelet sudo service kubelet status # 查看服务状态 ps -aux | grep kube-proxy kubectl cluster-info kubectl cluster-info dump # 详情 |
集群通信详情
集群通信概览
- 所有内容来自 API 服务
- 默认加密是 TSL(传输层加密)
- kubeadm 为 worker 节点创建证书
- 就为节点提供公用证书
- 通信路径
- API 服务对 kubelet
- 获取 pod 的日志
- 连接运行中的 pod
- 端口转发功能
- 验证连接 –kubelet-certificate-authority
- SSH通道
- API服务对其它(node, pod, services)
- 普通 HTTP 连接
- API 服务对 kubelet
Kubernetes 管理
部署、平滑升级和回滚
测试文件(nginx-dep.yaml)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
apiVersion: apps/v1 <em># for versions before 1.9.0 use apps/v1beta2</em> kind: Deployment metadata: name: nginx-dep spec: selector: matchLabels: app: nginx replicas: 2 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 |
使用kubectl create -f nginx-dep.yaml
命令创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
kubectl get deployments # 查看 kubectl describe deployment nginx-dep kubectl get deployment nginx-dep -o yaml # 导出 yaml kubectl set image deployment/nginx-dep nginx=nginx:1.8 # 升级 Nginx kubectl rollout status deployment/nginx-dep # 查看状态 kubectl describe deployment nginx-dep # 再次查看确定Nginx版本 # 第二种升级方式:编辑nginx-dep.yml 中的 image 版本(如1.9.1)然后执行 kubectl apply -f nginx-dep.yaml kubectl get deployments # 查看 kubectl describe deployment nginx-dep # 确认版本,其中也包含 revision的版本号(此处为3),如出现错误,可进行回滚 # 回滚 kubectl rollout history deployment/nginx-dep --revision=3 # 查看 kubectl rollout undo deployment/nginx-dep --to-revision=2 # 回滚 kubectl rollout status deployment/nginx-dep # 查看回滚状态 kubectl describe deployment nginx-dep # 再次确认 |
服务网络
1 2 3 4 |
kubectl expose deployment nginx-dep --type="NodePort" --port 80 kubectl get services # 查看服务 kubectl describe services nginx-dep # 查看具体服务 # 此时使用 worker 节点的 IP,加NodePort 即可在浏览器中进行访问,如 http://192.168.0.12:30523 |
Ingress
1 2 |
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml kubectl get pods --all-namespaces # 查看状态 |
创建 pod
web-01.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
apiVersion: v1 kind: Pod metadata: name: web-01 labels: app: Nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 |
使用kubectl create -f web-01.yaml
命令创建
1 2 3 |
kubectl get pods # 查看 kubectl expose pod web-01 --type="ClusterIP" --port 80 # 暴露端口 kubectl get services # 查看服务 |
ingress.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
apiVersion: v1 kind: Service metadata: name: ingress-nginx namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx spec: type: NodePort ports: - name: http-new port: 80 targetPort: 80 protocol: TCP nodePort: 30090 selector: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx |
使用kubectl create -f ingress.yaml
命令创建
1 |
kubectl get services --all-namespaces # 查看 |
ingress-rules.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-test annotations: kubernetes.io/ingress.class: nginx ingress.kubernetes.io/rewrite-target: / spec: rules: - host: test.kuber.net http: paths: - path: / backend: serviceName: web-01 servicePort: 80 |
使用kubectl create -f ingress-rules.yaml
命令创建
1 |
kubectl get ingress # 查看 |
在本地查看机器的 hosts 文件中绑定:
1 |
your.worker.node.ip test.kuber.net |
此时在浏览器中使用 http://test.kuber.net:30090/即可进行访问
部署负载均衡
loadbalancer.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
kind: Service apiVersion: v1 metadata: name: loadbalancer-service spec: selector: app: app-lb ports: - protocol: TCP port: 80 targetPort: 9376 clusterIP: <internalIP> loadBalancerIP: <externalIP> type: LoadBalancer |
配置和使用集群 DNS
1 |
kubectl get pods -n kube-system # 查看默认有 coredns |
busybox.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
vagrant@master-node:~$ clear apiVersion: v1 kind: Pod metadata: name: busybox namespace: default spec: containers: - image: busybox:1.28 command: - sleep - "3600" imagePullPolicy: IfNotPresent name: busybox restartPolicy: Always |
使用kubectl create -f busybox.yaml
命令创建
1 2 3 4 5 6 7 |
kubectl get pods # 查看创建进度 kubectl exec -it busybox -- nslookup kubernetes # 出现问题排查思路 kubectl exec -it busybox -- cat /etc/resolv.conf kubectl get pods -n kube-system kubectl get services -n kube-system kubectl get endpoints kube-dns -n kube-system |
补充:若执行以上命令出现unable to upgrade connection pod does not exist报错
1 2 3 4 5 6 7 8 9 10 |
kubectl get nodes <worker-node> -o yaml # 修改名称查看statuses中的addresses # 如为无法连接到的IP,则需进行修改 # 进入对应的工作节点 # vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf # 在EnvironmentFile=-/etc/default/kubelet行之后添加 Environment="KUBELET_EXTRA_ARGS=--node-ip=<your.ip.addr>" # 重启 systemctl daemon-reload systemctl restart kubelet # 若依然有问题则打执行 kubeadm reset 重新加入主节点 |
持久化存储
进入执行化存储所需的步骤:
- 创建 NFS 存储服务
- 在 Kubernetes 中配置持久化磁盘卷
- 声明持久化磁盘卷存储
- 创建 Pod
1 2 3 4 5 6 7 8 |
apt-get install nfs-kernel-server -y mkdir /var/nfs/general -p cd /var/nfs/ chown nobody:nogroup general/ id nobody # 查看用户 id,稍后使用 # vi /etc/exports 可在其中添加多个 worker node /var/nfs/general 192.168.x.x(rw,sync,no_subtree_check) 192.168.x.x(rw,sync,no_subtree_check) exportfs -r # 不执行这条可能后续可能会失败并报mount.nfs: access denied by server while mounting... |
在Master 节点添加pv.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
apiVersion: v1 kind: PersistentVolume metadata: name: kube-pv spec: capacity: storage: 1Gi volumeMode: Filesystem accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Recycle nfs: path: /var/nfs/general server: 192.168.0.11 readOnly: false |
使用kubectl create -f pv.yaml
命令创建
1 |
kubectl get pv # 查看 |
pvc.yaml
1 2 3 4 5 6 7 8 9 10 |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: kube-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi |
使用kubectl create -f pvc.yaml
命令创建
1 2 |
kubectl get pvc # 查看 kubectl get pv # 此时状态会变成Bound |
nfs-pod.yaml(65534 为 id nobody 所获取的值)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
apiVersion: v1 kind: Pod metadata: name: nfs-pod labels: name: nfs-pod spec: containers: - name: nfs-container image: busybox:1.28 command: - sleep - "3600" volumeMounts: - name: nfsvol mountPath: /tmp restartPolicy: Always securityContext: fsGroup: 65534 runAsUser: 65534 volumes: - name: nfsvol persistentVolumeClaim: claimName: kube-pvc |
使用kubectl create -f nfs-pod.yaml
命令创建
1 2 3 4 5 |
kubectl get pods # 查看创建状态 kubectl exec -it nfs-pod -- sh / $ cd /tmp /tmp $ touch hello.txt # 回到/var/nfs/general目录进行查看 |
自修复和自动伸缩
Kubernetes 自修复
1 2 3 4 5 6 7 8 |
kubectl get pods -o wide # 此前建立 nginx-dep 有两个 pod 来运行中 kubectl delete pod nginx-dep-9f46bb5-bck7x # 删除其中的一个 kubectl get pods -o wide # 再次查看会发现 Kubernetes 正在重新创建一个 # 进入一个 worker 节点停止服务 service kubelet stop # 几分钟后节点会显示为NotReady(kubectl get nodes) kubectl get pods -o wide # 此时如有多个节点会自动在其它节点上创建Pod |
Kubernetes 中的存活探针
存活探针类型
- HttpGet
- TCP
- Command
liveness.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-exec spec: containers: - name: liveness image: k8s.gcr.io/busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600 livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5 |
使用kubectl create -f liveness.yaml
命令创建
1 2 |
# 通过以下命令会看到存活探针失败并重启的提示 kubectl describe pod liveness-exec |
自动伸缩
什么是自动伸缩?
- 是根据不同时间所需资源来分配资源的过程
- 按需资源
- 成本节约
- Kubernetes 中的自动伸缩由指标驱动
- CPU使用量
- 内存使用量
- 每秒的请求
横向 Pod 自动伸缩
横向 Pod 自动伸缩(HPA)
步骤:
- 克隆一个 metric 服务
- 创建一个 Pod
- 配置 HPA
1 2 3 4 5 6 7 8 9 |
git clone https://github.com/kubernetes-incubator/metrics-server kubectl create -f metrics-server/deploy/1.8+/ # 同时对该目录下的所有 yaml 文件进行创建 kubectl get pods --all-namespaces # 查看启动状态 kubectl get --raw /apis/metrics.k8s.io/v1beta1 kubectl top nodes # 横向扩展示例 kubectl run php-apache --image=k8s.gcr.io/hpa-example --requests=cpu=200m --expose --port=80 kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=4 kubectl get hpa -w # 查看 |
metrics-server-deployment.yaml文件修改(Error from server (ServiceUnavailable): the server is currently unable to handle the request (get nodes.metrics.k8s.io))
1 2 3 4 5 6 7 8 9 10 |
containers: - name: metrics-server #image: k8s.gcr.io/metrics-server-amd64:v0.3.5 image: mirrorgooglecontainers/metrics-server-amd64:v0.3.5 # 国内被墙的问题 # 以下均作出了修改 imagePullPolicy: IfNotPresent command: - /metrics-server - --kubelet-insecure-tls - --kubelet-preferred-address-types=InternalIP |
监控类型
监控
监控让我们知道基础架构的性能和稳定性
两种主要类型的监控
基础架构监控
- 集中于基础架构的性能、加载速度等
应用性能监控
- 集中于应用所运行的基础架构上
两种展现数据的方式
聚合:视觉形式展现数据
警报:通知相关方
实现方案:
- Prometheus:收集信息及存储数据
- Grafana:展示数据
配置Prometheus和Grafana
配置 Prometheus 和 Grafana 的要求
- Helm 安装
- Charts
- 安装步骤
- 安装 Helm
- 下载 charts
- Values.yml文件自定义设置
- 在Grafana 中配置 Prometheus数据源并验证其连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
curl -L https://git.io/get_helm.sh | bash helm init --wait kubectl --namespace=kube-system create clusterrolebinding add-on-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default helm ls # 验证,无报错信息即为正常 git clone https://github.com/kubernetes/charts # vi prometheus-values.yml(仅测试使用) alertmanager: persistentVolume: enabled: false server: persistentVolume: enabled: false helm install -f prometheus-values.yml charts/stable/prometheus --name prometheus --namespace prometheus |