k8s

kubernetes 初探——在 Master 节点部署 Pod

虽然 K8S 本身不建议在 Master 节点中部署 Pod,但是实际上也是可以的。

kubectl taint nodes --all node-role.kubernetes.io/master-

这行命令的意思是移除所有节点的 master taint,这样就可以在 master 节点部署 pod 啦~

原理解释——taint 和 toleration

  1. https://www.ibm.com/support/knowledgecenter/en/SSCKRH1.0.1/platform/installpod_scheduling.html
  2. https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/

kubernetes 初探——服务治理

服务治理有两种方式:

  • 一种是直接在服务中集成熔断降级等操作
  • 一种是使用 sidecar 模式,有公共组件来处理

两种模式的区别如图:

服务

相关概念

Service. 如果一个 Deployment 对外(pod 外)提供服务的话,可以暴露为 Service。它是服务的抽象, 通过 kube-proxy 和 DNS 等提供负载均衡给后端 RC 定义的 Pod。服务一共有三种类型:

  • clusterIP. 服务暴露在集群内部的一个虚拟 IP,生命周期和服务相同
  • nodePort. 暴露在所有 Node 上的服务端口,不建议在生产环境使用。
  • LoadBalancer,通过外部的LB,暴露对应的服务。

另外还可以使用 Ingress Controller. Service 只是对集群内部暴露了服务,ingress controller 用于把 Service 再对外暴露。就相当于一个虚拟主机。

如果一个 deployment 需要对集群内部或者是外部提供服务的话,可以使用 service。

这时将创建一个 clusterIP,需要特别注意的是,这个 clusterIP 也是虚拟的,并没有和任何 pod 绑定,而是绑定到了服务上,可以理解为绑定到了这个服务对应的内部负载均衡上,并且是不变的。即使你的 Deployment 中指定了多个副本,那么也只有这一个 clusterIP,pod 的创建和销毁也都不会影响到 clusterIP。

参考资料

  1. Service Mesh 的本质、价值和应用探索
  2. Istio, K8S 的微服务支持
  3. 微服务之熔断、降级、限流
  4. 微服务化之服务拆分与服务发现

kubernetes 初探——使用 helm 部署服务

在 k8s 上部署一个应用还是有些复杂的, 自己的应用当然需要自己一步一步部署, 但是对于一些通用的应用, 比如说 mysql/grafana 这种就没必要自己手工一步一步部署了. 这时候就有了 helm, 通俗的来说他就是 kubernetes 上的 AppStore 或者是 apt-get, 常见的应用都已经在了, 而且你也可以按照他的格式打包自己的应用部署.

Helm 是 Kubernetes 的一个包管理器,你可以把他理解为 apt-get 或者 App Store。Helm 中的一个包称为一个 Chart,每次安装后称为一个 Release, Release 还有 revision,可以升级或者回滚到之前的 revision。 Helm 中还可以添加不同的 repo,repos 中有不同的 Chart。

安装

在 helm 的 release 页面下载, 然后拷贝到本地的 /usr/local/bin/ 目录就好了. helm 运行的时候会使用 ~/.kube/config 文件, 所以本地 kubectl 可以使用就好了.

使用

添加仓库

helm repo add stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts  # 国内镜像

安装包(Chart)

helm repo update  # 更新仓库
helm install stable/mysql --generate-name  # 安装一个包

列出值

helm list  # 列出当前的 release
helm status RELEASE # 查看状态

自定义安装

helm show values stable/mysql
helm install -f config.yaml stable/mysql --generate-name

升级和回滚

helm upgrade
helm rollback

卸载

helm uninstall

概念

  • Chart, 大概相当于 package 的意思
  • Repository, Helm 的中心仓库
  • Release, 每次运行一个 Chart 都会生成一个 Release, 每个 release 之间是独立的. Chart/Release 的关系就好比 Docker 的 Image/Container 一样.
  • Revision, 每次更新 Release 都会产生一个新的版本, 可以回滚

基础命令

helm search 查找相关的软件包(chart), 现在 stable 仓库中大概有 200 多个包可以安装.

helm install –name NAME PACKAGE 会安装对应的 chart. 如果不指定 name, 会自动生成一个.

helm status NAME 可以查看对应的包的信息, 一般包括了如何连接使用这个包等信息, 可以当做帮助来用.

在安装包之前更改配置

每个 helm chart 都定义了一些默认的配置, 可以在安装之前查看并修改这些值.

helm inspect values stable/mysql 查看 mysql 的默认值. 或者去 GitHub 上看这个仓库的 readme.

把需要覆盖的变量写到 OVERRIDE.yml 文件中, helm install -f OVERRIDE.yml stable/mysql 就可以使用自己的配置了

更新 release

如果需要更新一个 release, 可以使用 helm upgrade -f OVERRIDE.yml RELEASE_NAME 命令更新相关的配置. 这时就会创建一个新的版本.

使用 helm list 可以查看当前部署的 release, 这时候我们可以看到部署的版本变成了 2 (最初是1).

-> % helm ls
NAME    REVISION        UPDATED                         STATUS          CHART           NAMESPACE
mysql   1               Sat Oct  6 15:44:25 2018        DEPLOYED        mysql-0.3.0     default

如果当前的更新有误, 可以回退到之前的版本, 语法是 helm rollback [RELEASE] [REVISION]

管理 repo

helm repo list 列出当前添加的 repo

$ helm repo list
NAME            URL
stable          https://kubernetes-charts.storage.googleapis.com
local           http://localhost:8879/charts
mumoshu         https://mumoshu.github.io/charts

添加新的 repo

$ helm repo add dev https://example.com/dev-charts

基本使用

参考

  1. https://docs.helm.sh/
  2. https://ezmo.me/2017/09/24/helm-quick-toturial/
  3. https://help.aliyun.com/document_detail/58587.html
  4. https://johng.cn/helm-brief/
  5. https://www.lixf.io/2019/06/13/k8s-docker-images-mirrors/

kubernetes 初探——部署有状态服务

为了部署我们自己的应用, 首先需要把基础设施部署上去, 其中数据库就占了大头. 有人说数据库等应用不是和容器化部署, 但是也有人认为所有的应用都适合容器化部署. 在这里我们不讨论这些观点,仅以部署 MySQL 为例说明一下如何在 K8S 上部署有状态服务。

相关概念

  • PersistentVolume(PV) 是集群之中的一块网络存储。跟 Node 一样,也是集群的资源。PV 跟 Volume 类似,不过会有独立于 Pod 的生命周期。这一 API 对象包含了存储的实现细节,例如 NFS、iSCSI 或者其他的云提供商的存储系统。
  • PersistentVolumeClaim (PVC) 是用户的一个请求。他跟 Pod 类似。Pod 消费 Node 的资源,PVC 消费 PV 的资源。Pod 能够申请特定的资源(CPU 和 内存);Claim 能够请求特定的尺寸和访问模式(例如可以加载一个读写,以及多个只读实例)
  • Stateful Set. Deployment 是无状态的服务,而 StatefulSets 旨在与有状态的应用及分布式系统一起使用。
  • ConfigMap 用来保存非密码的配置. configmap 可以以配置文件或者环境变量等方式挂在到 pod 中
  • Secret 用来保存密码等私密数据
  • Init Container 用于初始化的容器. 有点类似于 docker build 的过程

动态 PV vs 静态 PV

使用 Deployment PVC 还是 Stateful Set

可以看出我们即可以使用普通的 Deployment + PVC 来部署 MySQL, 也可以使用 Stateful Set 来部署, 那么哪种方式更好呢?

个人理解:

  • 对于需要使用挂载一定资源的,使用 PVC 就好了,甚至只需要只读挂载就好。
  • 对于强状态依赖的服务,比如数据库,肯定要使用 PVC

Stack Overflow 上的一个问题[2]也很值得参考.

MySQL 主从集群

本文中我们要部署一个一主多从的 MySQL 集群. 关于一主多从的优点不是本文的重点, 这里就不多说了, 可以参考下面:

  1. 扩容解决方案:在多个slave之间扩展负载以提高性能。在这种模式下,所有的写入和更新操作都必须在主服务器上进行。然而,读取操作通过slave镜像。该模型可以提高写入操作的性能,同时,也能够通过增加slave的节点数量,从而显著地提升读取速度。
  2. 数据安全:数据从master被复制到slave,并且slave可以暂停复制过程。因此,可以在不损坏master的情况下,在slave上运行备份服务。
  3. 分析:现场数据可以在master上创建,而对信息的分析可以在slave进行,而不影响master的性能。
  4. 远程数据分发:可以使用复制为远程站点创建本地数据的副本,而不必一直通过访问master。

参考

  1. 使用 PVC 和 Deployment 部署单实例 MySQL 集群
  2. https://stackoverflow.com/questions/41732819/why-statefulsets-cant-a-stateless-pod-use-persistent-volumes
  3. 使用普通 Deployment 部署单节点 mysql
  4. https://kubernetes.io/cn/docs/tutorials/stateful-application/basic-stateful-set/
  5. 如何使用 ConfigMap
  6. Secret 文档
  7. https://stackoverflow.com/questions/41583672/kubernetes-deployments-vs-statefulsets
  8. 阿里云挂载 OSS Volume
  9. https://jimmysong.io/posts/kubernetes-persistent-volume/
  10. https://kubernetes.io/docs/concepts/storage/volumes/

kubernetes 初探——部署无状态应用

kubernetes 架构图

  • Master. 用于控制整个集群部署的机器,为了高可用,可以使用多台,一般至少三台为宜。
  • Node. 工作节点,用于部署服务。一台机器可以既是 Master 也是 Worker,当然最好 Master 不要做 Worker。
  • Pod. k8s 部署的最小单元,一个 Pod 中可能包含多个 container. Pod 随时可能挂掉,也可能被替换。
  • Label. Pod 的标签,可以通过这些标签(组合)来选择对应的 Pod。
  • Replica Set. 作为一个高可用的系统,每个服务一般来说可能有多个 Pod. Replication Set 用来创建并保证有足够的 Pod 副本。RS 的名字总是 <Deployment 的名字>-<pod template 的 hash 值> 格式的。
  • Deployment. 用户一般来说不会直接创建 Pod, 而是创建一个 Deployment 来部署服务。(在老版本中是创建 RC)
  • Namespace. 命名空间,默认情况下会有 kube-system 和 default 两个命名空间,kube-system 存放的是 k8s 系统的 pod 等资源,而用户部署的资源会在 default 命名空间中。
  • PersistendVolume. 如果把 Node 理解为抽象的 CPU 和内存资源,那么 PV 就可以理解为抽象的硬盘资源。我们通过 Pod 来使用 Node,因此我们也不直接使用 PV,而是通过 PersistentVolumeClaim 来使用 PV。
  • PersistentVolumeClaim. 存储声明,用来声明需要使用的存储资源。
  • Stateful Set. Deployment 对应的部署语义上没有状态的,而 StatefulSet 会充分运用 PV 和 PVC 实现 Pod 重启之间的状态保持。典型应用场景是数据库。
  • Label 和 Selector. K8S 中的资源全部都通过 Label 来标识的选择。

Deployment

deployment 是使用 k8s 部署服务直接操作的概念。其他的概念往往都是通过 deployment 来间接使用的,因此理解 deployment 至关重要。

一个典型的 deployment 配置文件如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80

deployment 的配置可以发生改变,如果只是 replica 的数目发生了改变,那么这只是一个简单的扩容或者缩容操作,k8s 只会简单的打开或者杀死新的 Pod。如果镜像、命令等参数发生了改变,那么 K8S 会把这次操作视为升级,也就是开始一个 RollOut 操作,创建新的 ReplicaSet。在这个过程中,如果 deployment 中的 spec 指定了保留历史 revision 的次数大于零,那么原有的 ReplicaSet 不会被删除,只是会被 Scale 到 0 而已,方便回滚。

文档:

Note: a Deployment’s rollout is triggered if and only if the Deployment’s pod template (i.e. .spec.template) is changed, e.g. updating labels or container images of the template. Other updates, such as scaling the Deployment, will not trigger a rollout.

https://stackoverflow.com/questions/42561791/right-way-to-update-deployments-on-kubernetes

  1. deployment 和 pod 的区别
  2. Kubernetes 基础概念
  3. 客户端和服务端服务发现
  4. kubernetes 命令表
  5. Kubernetes 之 kubectl 常用命令使用指南:1: 创建和删除
  6. Kubernetes 之 kubectl 常用命令
  7. Kubernetes 基本概念以及术语
  8. kubectl create 和 apply 的区别
  9. https://stackoverflow.com/questions/42561791/right-way-to-update-deployments-on-kubernetes
  10. https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
  11. K8S YAML 文件基础
  12. NodePort/LB/Ingress 三种方式的对比
  13. https://kubernetes.io/docs/tasks/access-application-cluster/service-access-application-cluster/

kubernetes 初探——部署集群

随着 docker cloud 的关闭,容器的编排工具之争似乎已经结束了,Docker Swarm 算是完了,Kubernetes 笑到了最后。然而 k8s 的组件众多,因此部署起来也很麻烦。为此,网上有不少的网上有不少的部署教程和脚本,包括但不限于:

  • kubesaz
  • minikube
  • kubespray
  • rke
  • kubernetes: the hard way

本文基于 ubuntu 18.04. CentOS 上好多默认设置都需要修改,因此建议大家基于 Ubuntu 部署 k8s。

使用 kubespray 安装 k8s

(零) 假设我们要在三台机器上安装,另外一台机器作为控制节点。其中每台都作为工作节点,两台作为 master 节点。

IP | 角色
————|———————–
10.4.17.165 | 控制节点,不参与 k8s 集群
10.4.17.167 | master, node
10.4.17.168 | master, node
10.4.17.169 | node

(一) 下载 kubespray 安装包,这里我们使用最新版 (2018.10), 可能需要安装 python3, 如果没有安装的话

VERSION=2.7.0

# download kubespray
wget https://github.com/kubernetes-incubator/kubespray/archive/v${VERSION}.tar.gz
tar xzf v${VERSION}.tar.gz

# install dependencies
pip3 install -r kubespray-${VERSION}/requirements.txt

(二) 生成部署的 hosts.ini

kubespray 中有一个脚本叫做 inventory_builder 用来生成部署的 hosts.ini

cd kubespray-v${VERSION}
cp -r inventory/sample inventory/mycluster
declare -a IPS=(10.4.17.167 10.4.17.168 10.4.17.169)
CONFIG_FILE=inventory/mycluster/hosts.ini python3 contrib/inventory_builder/inventory.py ${IPS[@]}

生成之后,可以查看生成的文件

cat inventory/mycluster/host.ini

[k8s-cluster:children]
kube-master·▸   ·
kube-node·▸ ·

[all]
node1 ▸  ansible_host=10.4.17.167 ip=10.4.17.167
node2 ▸  ansible_host=10.4.17.168 ip=10.4.17.168
node3 ▸  ansible_host=10.4.17.169 ip=10.4.17.169

[kube-master]
node1·▸ ·
node2·▸ ·

[kube-node]
node1·▸ ·
node2·▸ ·
node3·▸ ·

[etcd]
node1·▸ ·
node2·▸ ·
node3·▸ ·

[calico-rr]

[vault]
node1·▸ ·
node2·▸ ·
node3·▸ ·

(三) 修改一些配置

代理:

由于众所周知的原因,k8s 依赖的 gcr.io 在中国大陆范围内无法访问,我们可以使用代理访问,关于如何搭建代理超出了本文的范围。
假设我们的代理是 http://proxy.com:10086, 修改 inventory/mycluster/group_vars/all/all.yml 文件,设置 httpproxy 和 httpsproxy 两个变量。

下载 kubectl 到本机:

设置 kubectllocalhost 和 kubeconfiglocalhost 两个变量为 true. 安装完成后会在本机安装 kubectl, 并且可以使用 inventory/mycluster/artifacts/admin.conf 使用 kubectl.

(四) 部署

这里我们需要使用 tiger 用户,这个用户需要满足如下条件:

  1. 可以无密码远程登录
  2. 在远程主机上具有无密码 sudo 权限
ansible-playbook -i inventory/mycluster/hosts.ini cluster.yml --become --user tiger -v

大概过十几分钟就部署好了

(五) 验证

cd inventory/mycluster/artifacts
./kubectl.sh get nodes

NAME      STATUS    ROLES         AGE       VERSION
node1     Ready     master,node   1d        v1.11.3
node2     Ready     master,node   1d        v1.11.3
node3     Ready     node          1d        v1.11.3

参考

  1. HN 上关于 Docker Cloud 关闭的讨论
  2. 使用 Kubespray 部署生产可用的 Kubernetes 集群