from geekbang

Docker

Paas->Docker

Paas:Cgroup, Namespace,打包可执行文件+启动脚本
Docker: 镜像, 本地环境和云端环境一致

- docker build mirr
- docker run mirr

容器编排(Container Orchestration):用户如何通过某些工具或者配置来完成一组虚拟机以及关联资源的定义,配置,创建,删除等工作

容器技术的核心功能,是通过约束和修改进程的动态表现,从而为其创造出一个边界

Docker 原理

  • 容器静态视图: 挂载在/var/lib/docker/aufs/mnt/上的rootfs
  • 容器动态视图:Container Runtime, by Namespace,Cgroups

容器边界

  • 通过Namespace实现独立的pid机制
    • int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
  • 时间是不能被直接虚拟化的,/proc不能被直接分离
  • 通过Cgroups进行资源限制,限制一个进程组能使用的资源上线

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $ mount -t cgroup 
    cpuset on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
    cpu on /sys/fs/cgroup/cpu type cgroup (rw,nosuid,nodev,noexec,relatime,cpu)
    cpuacct on /sys/fs/cgroup/cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct)
    blkio on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
    memory on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
    # occupy 100% cpu
    $ while : ; do : ; done &
    [1] 226
    $ top
    # get cpu quota, cpu period
    $ cat /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us
    -1
    $ cat /sys/fs/cgroup/cpu/container/cpu.cfs_period_us
    100000
    # set boundary
    $ echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us
    • docker 限制指令$ docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash
      1
      2
      3
      4
      $ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_period_us 
      100000
      $ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_quota_us
      20000
  • Linux 支持7种namespace:

    1. cgroup用于隔离cgroup根目录;
    2. IPC用于隔离系统消息队列;
    3. Network隔离网络;
    4. Mount隔离挂载点;
    5. PID隔离进程;
    6. User隔离用户和用户组;
    7. UTS隔离主机名nis域名。

单进程模型

  • 用户进程pid=1
  • 容器和应用同生命周期

增量设计

  • 用户制作镜像的每一步操作,都会生成一层增量rootfs
  • Docker使用的AuFS默认关键目录为/var/lib/docker/aufs/diff/<layer_id>
  • 可读写层的实现,删除添加.wh.filename

Docker 常用命令

安装Docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#CentOS
sudo yum install yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce
sudo systemctl enable docker
sudo systemctl start docker

#Debian
sudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install docker-ce
sudo systemctl enable docker
sudo systemctl start docker

添加国内镜像源

1
2
3
4
5
6
7
vim /etc/docker/daemon.json
{
"registry-mirrors": [
"https://registry.docker-cn.com"
]
}
sudo systemctl restart docker

建立镜像

demo code

1
2
ls
app.py requirements.txt Dockerfile
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from flask import Flask
import socket
import os

app = Flask(__name__)

@app.route('/')
def hello():
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname())

if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
requirements.txt
1
2
$ cat requirements.txt
Flask
Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 使用官方提供的 Python 开发镜像作为基础镜像
FROM python:2.7-slim

# 将工作目录切换为 /app
WORKDIR /app

# 将当前目录下的所有内容复制到 /app 下
ADD . /app

# 使用 pip 命令安装这个应用所需要的依赖
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# 允许外界访问容器的 80 端口
EXPOSE 80

# 设置环境变量
ENV NAME World

# 设置容器进程为:python app.py,即:这个 Python 应用的启动命令
CMD ["python", "app.py"]

build & run

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
# build
docker build -t helloworld .

# get id
$ docker image ls
REPOSITORY TAG IMAGE ID
helloworld latest 653287cdf998
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
4ddf4638572d helloworld "python app.py" 10 seconds ago

# run
$ docker run -p 4000:80 helloworld
$ curl http://localhost:4000

# push dockerhub
$ docker login
$ docker tag helloworld geektime/helloworld:v1
$ docker push geektime/helloworld:v1

# commit runtime
$ docker exec -it 4ddf4638572d /bin/sh
# 在容器内部新建了一个文件
root@4ddf4638572d:/app# touch test.txt
root@4ddf4638572d:/app# exit

# 将这个新建的文件提交到镜像中保存
$ docker commit 4ddf4638572d geektime/helloworld:v2

Kubernetes

https://github.com/kubernetes/client-go

aim

  • 运行大规模集群中各种任务之间,存在着各种各样的关系。这些关系的处理才是作业编排和管理系统最困难的地方
  • 借助Docker容器化思想,原先拥挤在一个虚拟机的各种进程分别做成镜像,互不干涉,有各自的资源配额

对象管理

命令式指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 创建一个deployment来运行nginx容器
kubectl run nginx --image nginx
kubectl create deployment nginx --image nginx
# 不能提供审查流程进行集成

- run:创建一个新的 Deployment 对象,以在一个或多个 Pod 中运行容器。
- expose:创建一个新的 Service 对象,以跨多个 Pod 来实现流量的负载均衡。
- autoscale:创建一个新的 Autoscaler 对象,以自动水平缩放控制器,如 Deployment
- create <对象类型> [<子类型>] <实例名> (kubectl create service 命令为 Service 创建配置并将其保存到 /tmp/srv.yaml)
- scale:通过更新控制器的副本计数来水平缩放控制器以添加或删除 Pod。
- annotate:从对象中添加或删除注释。
- label:从对象中添加或删除标签。
- edit:通过在编辑器中打开其配置直接编辑活动对象的原始配置。
- patch:使用修补程序字符串直接修改活动对象的特定字段。 有关修补程序字符串的更多详细信息,请参阅 API 约定 中的修补程序部分 。
- delete <类型>/<名称>
- get:打印有关匹配对象的基本信息。使用 get -h 查看选项列表。
- describe:打印有关匹配对象的汇总详细信息。
- logs:打印在 Pod 中运行的一个容器的 stdout 和 stderr。

命令式配置

1
2
3
4
5
6
7
8
9
10
11
#创建在配置文件中定义的对象:
kubectl create -f nginx.yaml

#删除两个配置文件中定义的对象:
kubectl delete -f nginx.yaml -f redis.yaml

#通过重写实时配置,更新配置文件中定义的对象。
kubectl replace -f nginx.yaml

#您可以使用 kubectl get -f 查看有关配置文件中描述的对象的信息。
kubectl get -f <文件名称|url> -o yaml

命令-》配置

1
2
3
4
5
从命令式命令迁移到命令式对象配置需要几个手动步骤。
# 将活动对象导出到本地对象配置文件:
kubectl get <kind>/<name> -o yaml --export > <kind>_<name>.yaml
# 手动从对象配置文件中删除状态字段。对于后续的对象管理,只使用 replace。
kubectl replace -f <kind>_<name>.yaml

声明式对象配置

用户不会定义对文件的操作。 创建、更新和删除操作由 kubectl 逐个对象自动进行检测。 这使得该技术能够作用于目录, 目录中的不同对象可能需要不同的操作。

1
2
3
4
5
#处理 configs 目录中的所有对象配置文件,并创建或对活动对象打补丁(patch):
kubectl apply -f configs/

#递归地处理目录:
kubectl apply -R -f configs/

配置-》声明

1
2
3
4
Migrating from imperative object configuration to declarative object configuration
Set the kubectl.kubernetes.io/last-applied-configuration annotation on the object:

kubectl replace --save-config -f <kind>_<name>.yaml

k8s原理

编排对象

  • 如何容器化特定的应用:job描述一次性运行的pod,cronjob描述定时任务

服务对象

  • 对互相频繁访问的多个容器,划分为一个pod,共享同一个network namespace,数据卷。
  • 给pod绑定一个service服务,其ip地址是不变的,作为pod的代理入口
  • Secret对象是一个保存在Etcd里的键值对数据,用于存储Credential信息,pod启动时自动挂载到容器内

k8s部署

参考

yum install

1
2
3
4
5
6
7
8
9
10
11
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
EOF
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
setenforce 0
yum install -y kubelet-1.10.9 kubeadm-1.10.9 kubectl-1.10.9 --disableexcludes=kubernetes
systemctl enable docker && systemctl start docker
systemctl enable kubelet && systemctl start kubelet

# 安装最新版本请执行
setenforce 0
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl enable docker && systemctl start docker
systemctl enable kubelet && systemctl start kubelet

cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

systemctl daemon-reload
systemctl restart kubelet

kubeadm config images list
images=(kube-proxy-amd64:v1.10.9 kube-scheduler-amd64:v1.10.9 kube-controller-manager-amd64:v1.10.9 kube-apiserver-amd64:v1.10.9
etcd-amd64:3.1.12 pause-amd64:3.1 kubernetes-dashboard-amd64:v1.8.3 k8s-dns-sidecar-amd64:1.14.8 k8s-dns-kube-dns-amd64:1.14.8
k8s-dns-dnsmasq-nanny-amd64:1.14.8)
for imageName in ${images[@]} ; do
docker pull registry.aliyuncs.com/google_containers/$imageName
docker tag registry.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
docker rmi registry.aliyuncs.com/google_containers/$imageName
done

dashboard

1
2
3
4
5
6
7
8
#Create a new ServiceAccount
kubectl create serviceaccount k8sadmin -n kube-system

#Create a ClusterRoleBinding with Cluster Admin Privileges
kubectl create clusterrolebinding k8sadmin --clusterrole=cluster-admin --serviceaccount=kube-system:k8sadmin

#Get the token
kubectl get secret -n kube-system | grep k8sadmin | cut -d " " -f1 | xargs -n 1 | xargs kubectl get secret -o 'jsonpath={.data.token}' -n kube-system | base64 --decode

apt install

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
增加kubernetes aliyun镜像源
apt-get update && apt-get install -y apt-transport-https
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
$ apt-get update
# apt-get install -y docker.io kubeadm
apt remove kubelet kubectl kubeadm
apt install kubelet=1.11.3-00
apt install kubectl=1.11.3-00
apt install kubeadm=1.11.3-00

kubeadm config images list --kubernetes-version v1.11.2
docker pull anjia0532/google-containers.kube-controller-manager-amd64:v1.11.2
docker tag anjia0532/google-containers.kube-controller-manager-amd64:v1.11.2 k8s.gcr.io/kube-controller-manager-amd64:v1.11.2
docker rmi anjia0532/google-containers.kube-controller-manager-amd64:v1.11.2

墙外服务器

1
2
3
4
5
6
7
8
9
10
$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
$ cat <<EOF > /etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
$ apt-get update
# apt-get install -y docker.io kubeadm
apt remove kubelet kubectl kubeadm
apt install kubelet=1.11.3-00
apt install kubectl=1.11.3-00
apt install kubeadm=1.11.3-00

start yaml

  • 1.11

    1
    2
    3
    4
    5
    6
    7
    8
    9
    apiVersion: kubeadm.k8s.io/v1alpha1
    kind: MasterConfiguration
    controllerManagerExtraArgs:
    horizontal-pod-autoscaler-use-rest-clients: "true"
    horizontal-pod-autoscaler-sync-period: "10s"
    node-monitor-grace-period: "10s"
    apiServerExtraArgs:
    runtime-config: "api/all=true"
    kubernetesVersion: "stable-1.11"
  • 1.13

    1
    2
    3
    4
    5
    6
    7
    8
    9
    apiVersion: kubeadm.k8s.io/v1alpha3
    kind: ClusterConfiguration
    controllerManagerExtraArgs:
    horizontal-pod-autoscaler-use-rest-clients: "true"
    horizontal-pod-autoscaler-sync-period: "10s"
    node-monitor-grace-period: "10s"
    apiServerExtraArgs:
    runtime-config: "api/all=true"
    kubernetesVersion: "stable-1.13"
  • 初始化

    1
    2
    3
    4
    kubeadm init --config kubeadm.yaml
    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
  • 配置网络插件 kubectl apply -f https://git.io/weave-kube-1.6

    • CNI通用接口,如Flannel,Calico,Canal,Romana
  • join:kubeadm join 172.31.50.50:6443 --token gfa18b.ydalqlu21rl3d4g5 --discovery-token-ca-cert-hash sha256:903afafec37fc3a4ba3ef60da50cdb6f702845536eaac76e57e1a94c2813be3d

dashboard

1
2
# kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

存储Rook

1
2
3
$ kubectl apply -f https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/operator.yaml

$ kubectl apply -f https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/cluster.yaml

常用策略

  • 污点,所有pod不能在这个节点上运行$ kubectl taint nodes node1 foo=bar:NoSchedule

    1
    2
    3
    4
    5
    6
    7
    8
    9
    apiVersion: v1
    kind: Pod
    ...
    spec:
    tolerations:
    - key: "foo"
    operator: "Equal"
    value: "bar"
    effect: "NoSchedule"
  • 单节点k8s:$ kubectl taint nodes --all node-role.kubernetes.io/master-

部署应用demo

  1. 本地通过Docker测试代码,制作镜像
  2. 选择合适的Kubernetes API对象,编写对应的YAML文件
  3. K8s上部署YAML文件
  • 部署之后要么通过kubectl,要目通过YAML,尽量不要使用docker的命令行

  • api: k8s支持多个api版本,alpha级别,beta级别,稳定级别

  • nginx-deployment.yaml

    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
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: nginx-deployment
    spec:
    selector:
    matchLabels:
    app: nginx
    replicas: 2
    template:
    metadata:
    labels:
    app: nginx
    spec:
    containers:
    - name: nginx
    image: nginx:1.8
    ports:
    - containerPort: 80
    volumeMounts:
    - mountPath: "/usr/share/nginx/html"
    name: nginx-vol
    volumes:
    - name: nginx-vol
    emptyDir: {}
  • kubectl apply -f nginx-deployment.yaml

  • kubectl delete -f nginx-deployment.yaml

pod

  • pod 是k8s的原子调度单位,是一组共享了某些资源(同一个Network Namespace, 可以共享同一个Volume)的容器
    • $ docker run --net=B --volumes-from=B --name=A image-A
    • infra容器共享Network Namespace
  • 同一个pod内的容器A和B:
    • 可以直接用localhost通信,网络设备和infra完全一样
  • 一个pod只有一个ip,就是其network namespace对应的ip
  • pod的生命周期只和infra容器一致,与容器A和B无关
  • 当用户想在一个容器里跑多个功能不相关的应用时,应该优先考虑它们是不是更应该被描述成一个pod内的多个容器
  • init container 定义容器都启动并且退出了,用户容器才会启动
  • sidecar指我们可以在一个pod中,启动一个辅助容器,来完成一些独立于主容器之外的工作
  • pod是传统部署环境里“虚拟机”的角色
  • nodeSelector:要求绑定pod的node属性
  • nodeName:一旦被赋值,k8s认为这个pod已经被调度
  • HostAliases定义了Pod的/etc/hosts文件内容
  • shareProcessNamespace=true:共享pid的namespace
  • Container
    • ImagePullPolicy拉取镜像策略
    • Lifecycle Hooks
  • status
    • penging:api对象已经被创建,但是container没有被创建或调度
    • running:pod已经被调度成功
    • succeeded:pod内所有容器运行完毕
    • failed:pod内至少一个容器以非0状态码退出
    • unknown:可能是主从节点通信出现问题
  • Project Volume
    • Secret
    • ConfigMap
    • Downward API
    • ServiceAccountToken

控制器模式

利用deploy和apply实现

  • label利用selector实现tag功能
  • annotations不能表示选择对象

ReplicaSet

是Deployment的一个子集,有副本数目定义的一个Pod模板
kubectl get rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-set
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
  • ReplicaSet通过控制器模式,保证pod的个数永远等于指定的个数
    • 水平扩展:kubectl scale deployment nginx-deployment --replicas=4
    • 查看Deploy对象状态的变化:kubectl rollout status
    • 修改Deployment的api对象:kubectl edit deployment/nginx-deployment
    • 修改镜像版本号:$ kubectl set image deployment/nginx-deployment nginx=nginx:1.91
    • 回滚:$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
    • 不生成新的ReplicaSet:$ kubectl rollout pause/resume

StatefulSet

  • 拓扑状态,存储状态
  • headless service: <pod-name>.<svc-name>.<namespace>.svc.cluster.local
  • 使用pod模板创建pod的时候,对它们进行编号,并且按照编号顺序逐一完成创建工作
  • statefulset为每一个pod分配并创建一个同样编号的pvc

Persistent Volume Claim

  • 在pod里加上spec.volumes字段即可声明volume

    • step1: 声明pvc

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      kind: PersistentVolumeClaim
      apiVersion: v1
      metadata:
      name: pv-claim
      spec:
      accessModes:
      - ReadWriteOnce
      resources:
      requests:
      storage: 1Gi
    • step2: 使用pvc

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      apiVersion: v1
      kind: Pod
      metadata:
      name: pv-pod
      spec:
      containers:
      - name: pv-container
      image: nginx
      ports:
      - containerPort: 80
      name: "http-server"
      volumeMounts:
      - mountPath: "/usr/share/nginx/html"
      name: pv-storage
      volumes:
      - name: pv-storage
      persistentVolumeClaim:
      claimName: pv-claim
  • pvc绑定到运维维护的PV对象,PVC和PV的设计,类似于接口和实现的思想

DaemonSet

每个节点存在并仅存在一个。可用于容器网络,远程存储目录,监控信息与日志收集
通过五点实现

Job

管理离线业务

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: resouer/ubuntu-bc
command: ["sh", "-c", "echo 'scale=10000; 4*a(1)' | bc -l "]
restartPolicy: Never
backoffLimit: 4

  • spec.backoffLimit: 重试次数
  • spec.activeDeadlineSeconds:执行时间限制
  • spec.parallelism:最多使用pod数目
  • spec.completions:至少要完成pod数目

CronJob

  • spec.schedule*/1 * * * **表示从0开始,/表示便宜了
  • spec.jobTemplate: Job控制器

PV

  • static Provisioning:通过yaml手动创建pv
  • Dynamic Provisioning:通过用户提交的pvc自动创建pv

Deployment

ReplicationController

rc,rcs:跨节点监控维护pod数目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

建议使用Deployment进行替代。

Deployment

您只需要在 Deployment 中描述您想要的目标状态是什么,Deployment controller 就会帮您将 Pod 和 ReplicaSet 的实际状态改变到您的目标状态。您可以定义一个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 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
假如我们现在想要让 nginx pod 使用nginx:1.9.1的镜像来代替原来的nginx:1.7.9的镜像。

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment "nginx-deployment" image updated
我们可以使用edit命令来编辑 Deployment,修改 .spec.template.spec.containers[0].image ,将nginx:1.7.9 改写成 nginx:1.9.1。

$ kubectl edit deployment/nginx-deployment
deployment "nginx-deployment" edited
查看 rollout 的状态,只要执行:

$ kubectl rollout status deployment/nginx-deployment

首先,检查下 Deployment 的 revision:

$ kubectl rollout history deployment/nginx-deployment

现在,我们可以决定回退当前的 rollout 到之前的版本:

$ kubectl rollout undo deployment/nginx-deployment
deployment "nginx-deployment" rolled back
也可以使用 --revision参数指定某个历史版本:

$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment "nginx-deployment" rolled back

Deployment 扩容:您可以使用以下命令扩容 Deployment:

$ kubectl scale deployment nginx-deployment --replicas 10
deployment "nginx-deployment" scaled
假设您的集群中启用了horizontal pod autoscaling,您可以给 Deployment 设置一个 autoscaler,基于当前 Pod的 CPU 利用率选择最少和最多的 Pod 数。

$ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
deployment "nginx-deployment" autoscaled

Metrix

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
$ git clone https://github.com/kubernetes-incubator/metrics-server
$ cd metrics-server
$ kubectl create -f deploy/1.8+/

# https://github.com/resouer/kubeadm-workshop
$ kubectl apply -f demos/monitoring/prometheus-operator.yaml
clusterrole "prometheus-operator" created
serviceaccount "prometheus-operator" created
clusterrolebinding "prometheus-operator" created
deployment "prometheus-operator" created

$ kubectl apply -f demos/monitoring/sample-prometheus-instance.yaml
clusterrole "prometheus" created
serviceaccount "prometheus" created
clusterrolebinding "prometheus" created
prometheus "sample-metrics-prom" created
service "sample-metrics-prom" created

$ kubectl apply -f demos/monitoring/custom-metrics.yaml
namespace "custom-metrics" created
serviceaccount "custom-metrics-apiserver" created
clusterrolebinding "custom-metrics:system:auth-delegator" created
rolebinding "custom-metrics-auth-reader" created
clusterrole "custom-metrics-read" created
clusterrolebinding "custom-metrics-read" created
deployment "custom-metrics-apiserver" created
service "api" created
apiservice "v1beta1.custom-metrics.metrics.k8s.io" created
clusterrole "custom-metrics-server-resources" created
clusterrolebinding "hpa-controller-custom-metrics" created

$ kubectl create clusterrolebinding allowall-cm --clusterrole custom-metrics-server-resources --user system:anonymous
clusterrolebinding "allowall-cm" created

$ kubectl apply -f demos/monitoring/sample-metrics-app.yaml
deployment "sample-metrics-app" created
service "sample-metrics-app" created
servicemonitor "sample-metrics-app" created
horizontalpodautoscaler "sample-metrics-app-hpa" created
ingress "sample-metrics-app" created

$ # Install hey
$ docker run -it -v /usr/local/bin:/go/bin golang:1.8 go get github.com/rakyll/hey

$ export APP_ENDPOINT=$(kubectl get svc sample-metrics-app -o template --template {{.spec.clusterIP}}); echo ${APP_ENDPOINT}
$ hey -n 50000 -c 1000 http://${APP_ENDPOINT}

$ curl -sSLk https://10.100.206.10/apis/custom-metrics.metrics.k8s.io/v1beta1/namespaces/default/services/sample-metrics-app/http_requests
{
"kind": "MetricValueList",
"apiVersion": "custom-metrics.metrics.k8s.io/v1beta1",
"metadata": {
"selfLink": "/apis/custom-metrics.metrics.k8s.io/v1beta1/namespaces/default/services/sample-metrics-app/http_requests"
},
"items": [
{
"describedObject": {
"kind": "Service",
"name": "sample-metrics-app",
"apiVersion": "/__internal"
},
"metricName": "http_requests",
"timestamp": "2018-11-30T20:56:34Z",
"value": "501484m"
}
]
}