4

深入Kubernetes(一):Kubernetes部署&在Kubernetes中运行第一个程序

 3 years ago
source link: http://dockone.io/article/1326663
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

搭建Kubernetes单点实验环境

由于在国内网络问题,我们无法很好的使用Minikube进行部署Kubernetes实验环境,所以可以使用阿里提供的minikube进行搭建。除了minikube,也可以使用kubeasz进行部署。

下面我基于kubeaze给出部署方法,部署方法都参照https://github.com/easzlab/kubeasz,其中附上我的踩坑经验。

基础系统配置

  • 准备一台虚机配置内存2G/硬盘30G以上
  • 最小化安装Ubuntu 16.04 server或者CentOS 7 Minimal
  • 配置基础网络、更新源、SSH登录等
注意:确保在干净的系统上开始安装,不能使用曾经装过kubeadm或其他Kubernetes发行版的环境
下载工具脚本easzup,举例使用kubeasz版本2.2.1。
export release=2.2.1
curl -C- -fLO --retry 3 https://github.com/easzlab/kubeasz/releases/download/${release}/easzup
chmod +x ./easzup

使用工具脚本下载。

默认下载最新推荐Kubernetes/Docker等版本,使用命令./easzup查看工具脚本的帮助信息。

设置Docker源:
{
"registry-mirrors": [
"https://eig40bb2.mirror.aliyuncs.com",
"https://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com",
"https://reg-mirror.qiniu.com"
],
"max-concurrent-downloads": 10,
"log-driver": "json-file",
"log-level": "warn",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"data-root": "/var/lib/docker"


添加完之后刷新一下配置:
systemctl daemon-reload
systemctl restart docker
# 举例使用 Kubernetes 版本 v1.18.2,Docker 19.03.5
./easzup -D -d 19.03.5 -k v1.18.2

可选下载离线系统包(适用于无法使用yum/apt仓库情形)。
./easzup -P

上述脚本运行成功后,所有文件(kubeasz代码、二进制、离线镜像)均已整理好放入目录/etc/ansible。
  • /etc/ansible包含kubeasz版本为${release}的发布代码
  • /etc/ansible/bin包含Kubernetes/etcd/Docker/CNI等二进制文件
  • /etc/ansible/down包含集群安装时需要的离线容器镜像
  • /etc/ansible/down/packages包含集群安装时需要的系统基础软件
容器化运行 kubeasz。
./easzup -S

使用默认配置安装aio集群。
docker exec -it kubeasz easzctl start-aio

如果提示kubectl: command not found,退出重新SSH登录一下,环境变量生效即可。
$ kubectl version         # 验证集群版本     
$ kubectl get node        # 验证节点就绪(Ready)状态
$ kubectl get pod -A      # 验证集群Pod状态,默认已安装网络插件、coredns、metrics-server等
$ kubectl get svc -A      # 验证集群服务状态

搭建Kubernetes集群环境

我们打算搭建一个这样的三节点的集群:

准备服务器

首先3台虚机,搭建一个多主高可用集群。
  • 推荐内存2G/硬盘30G以上
  • 最小化安装Ubuntu 16.04 server或者CentOS 7 Minimal
  • 配置基础网络、更新源、SSH登录等

在每个节点安装Ansible依赖工具

CentOS 7请执行以下脚本:
# 文档中脚本默认均以root用户执行
yum update
# 安装Python
yum install python -y

安装pip的时候先安装。
yum -y install epel-release

安装pip。
yum install git python-pip -y

pip安装Ansible。
# CentOS 7
yum install git python-pip -y
# pip安装Ansible(国内如果安装太慢可以直接用pip阿里云加速)
pip install pip --upgrade -i https://mirrors.aliyun.com/pypi/simple/
pip install ansible==2.6.18 netaddr==0.7.19 -i https://mirrors.aliyun.com/pypi/simple/

在Ansible控制端配置免密码登录。
# 更安全Ed25519算法
ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519
# 或者传统RSA算法
ssh-keygen -t rsa -b 2048 -N '' -f ~/.ssh/id_rsa

ssh-copy-id 192.168.13.131
ssh-copy-id 192.168.13.132
ssh-copy-id 192.168.13.133

如果这一步不设置,那么在部署的时候无法访问到相应的节点会报如下错:
192.168.13.130 | UNREACHABLE! => {
"changed": false,
"msg": "SSH Error: data could not be sent to remote host \"192.168.13.130\". Make sure this host can be reached over ssh",
"unreachable": true

在Ansible控制端编排Kubernetes安装

  • 下载项目源码
  • 下载二进制文件
  • 下载离线Docker镜像
推荐使用easzup脚本下载4.0/4.1/4.2所需文件;运行成功后,所有文件(kubeasz代码、二进制、离线镜像)均已整理好放入目录/etc/ansible。
# 下载工具脚本easzup,举例使用kubeasz版本2.0.2
export release=2.0.2
curl -C- -fLO --retry 3 https://github.com/easzlab/kubeasz/releases/download/${release}/easzup
chmod +x ./easzup
# 使用工具脚本下载
./easzup -D

配置集群参数

必要配置:cd/etc/ansible && cp example/hosts.multi-node hosts,然后实际情况修改此hosts文件。

根据我们上图的介绍,我们将hosts改成如下:
# 'etcd' cluster should have odd member(s) (1,3,5,...)
# variable 'NODE_NAME' is the distinct name of a member in 'etcd' cluster
[etcd]
192.168.13.131 NODE_NAME=etcd1
192.168.13.132 NODE_NAME=etcd2
192.168.13.133 NODE_NAME=etcd3

# master node(s)
[kube-master]
192.168.13.131

# work node(s)
[kube-node]
192.168.13.131
192.168.13.132
192.168.13.133

...

只改如上配置,其他的可不动。

验证Ansible安装:ansible all -m ping正常能看到节点返回SUCCESS。

开始安装,如果你对集群安装流程不熟悉,请阅读项目首页安装步骤,讲解后分步安装,并对每步都进行验证。
# 分步安装
ansible-playbook 01.prepare.yml
ansible-playbook 02.etcd.yml
ansible-playbook 03.docker.yml
ansible-playbook 04.kube-master.yml
ansible-playbook 05.kube-node.yml
ansible-playbook 06.network.yml
ansible-playbook 07.cluster-addon.yml

如果不想分步安装,那么可以一步安装:
# 一步安装
#ansible-playbook 90.setup.yml

在Kubernetes中运行一个程序

编写YAML文件

Kubernetes跟Docker等很多项目最大的不同,就在于它不推荐你使用命令行的方式直接运行容器,而是希望你用YAML文件的方式,然后用这样一句指令把它运行起来:
$ kubectl create -f 我的配置文件

yaml如下:
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.7.9
    ports:
    - containerPort: 80

Kind字段,指定了这个API对象的类型(Type),是一个Deployment。Deployment,是一个定义多副本应用的对象,Deployment还负责在Pod定义发生变化时,对每个副本进行滚动更新。

像这样使用一种API对象(Deployment)管理另一种API对象(Pod)的方法,在Kubernetes中,叫作“控制器”模式(controller pattern)。

一个Kubernetes的API对象的定义,大多可以分为Metadata和Spec两个部分。前者存放的是这个对象的元数据,对所有API对象来说,这一部分的字段和格式基本上是一样的;而后者存放的,则是属于这个对象独有的定义,用来描述它所要表达的功能。

spec.replicas是2,表示定义的 Pod 副本个数。

spec.template作用是描述了我想要创建的 Pod 的细节。spec.containers.image表示容器镜像是nginx:1.7.9,containerPort表示监听的端口是80。

Labels字段可以用来过滤控制对象,在上面这个YAML文件中,Deployment会把所有正在运行的、携带“app: nginx”标签的Pod识别为被管理的对象,并确保这些Pod的总数严格等于两个。

spec.selector.matchLabels是用来定义过滤规则的,一般称之为:Label Selector。

创建一个Pod

在理解完上面的知识后,我们可以运行起来:
$ kubectl create -f nginx-deployment.yaml

然后,通过kubectl get命令检查这个YAML运行起来的状态是不是与我们预期的一致:
$ kubectl get pods -l app=nginx
NAME                                READY     STATUS    RESTARTS   AGE
nginx-deployment-67594d6bf6-9gdvr   1/1       Running   0          10m
nginx-deployment-67594d6bf6-v6j7w   1/1       Running   0          10m

-l表示获取所有匹配app: nginx标签的Pod。

注意:在命令行中,所有key-value格式的参数,都使用“=”而非“:”表示。

此外,我们还可以使用kubectl describe命令,查看一个API对象的细节:
$ kubectl describe pod nginx-deployment-67594d6bf6-9gdvr
Name:               nginx-deployment-67594d6bf6-9gdvr
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               node-1/10.168.0.3
Start Time:         Thu, 16 Aug 2018 08:48:42 +0000
Labels:             app=nginx
                pod-template-hash=2315082692
Annotations:        <none>
Status:             Running
IP:                 10.32.0.23
Controlled By:      ReplicaSet/nginx-deployment-67594d6bf6
...
Events:

Type     Reason                  Age                From               Message

----     ------                  ----               ----               -------

Normal   Scheduled               1m                 default-scheduler  Successfully assigned default/nginx-deployment-67594d6bf6-9gdvr to node-1
Normal   Pulling                 25s                kubelet, node-1    pulling image "nginx:1.7.9"
Normal   Pulled                  17s                kubelet, node-1    Successfully pulled image "nginx:1.7.9"
Normal   Created                 17s                kubelet, node-1    Created container
Normal   Started                 17s                kubelet, node-1    Started container

上面详细信息中,在Kubernetes执行的过程中,对API对象的所有重要操作都会记录到Events里面。

为Pod进行版本升级

如果我们要对这个Nginx服务进行升级,把它的镜像版本从1.7.9升级为1.8,那么我们可以修改一下YAML文件:
...    
spec:
  containers:
  - name: nginx
    image: nginx:1.8 #这里被从1.7.9修改为1.8
    ports:
  - containerPort: 80

然后使用kubectl replace指令来完成Kubernetes集群中更新:
$ kubectl replace -f nginx-deployment.yaml

我们也可以使用kubectl apply命令,来统一进行Kubernetes对象的创建和更新操作,具体做法如下所示:
$ kubectl apply -f nginx-deployment.yaml

# 修改nginx-deployment.yaml的内容

$ kubectl apply -f nginx-deployment.yaml

使用kubectl apply命令是Kubernetes“声明式API”所推荐的使用方法。也就是说,作为用户,你不必关心当前的操作是创建,还是更新,你执行的命令始终是kubectl apply,而Kubernetes则会根据YAML文件的内容变化,自动进行具体的处理。

声明一个Volume

在Kubernetes中,Volume是属于Pod对象的一部分。所以,我们就需要修改这个YAML文件里的template.spec字段,如下所示:
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: {} 

我们在上面定义了volumes字段,名字叫做nginx-vol,类型是emptyDir。Pod中的容器,使用的是volumeMounts字段来声明自己要挂载哪个Volume,并通过mountPath字段来定义容器内的Volume目录,比如:/usr/share/nginx/html。

emptyDir表示,Kubernetes也会在宿主机上创建一个临时目录,这个目录将来就会被绑定挂载到容器所声明的Volume目录上。

然后使用kubectl apply 指令,更新这个Deployment,然后使用kubectl describe查看一下最新的Pod:
...
Containers:
nginx:
Container ID:   docker://07b4f89248791c2aa47787e3da3cc94b48576cd173018356a6ec8db2b6041343
Image:          nginx:1.8
...
Environment:    <none>
Mounts:
  /usr/share/nginx/html from nginx-vol (rw)
...
Volumes:
nginx-vol:
Type:    EmptyDir (a temporary directory that shares a pod's lifetime)

最后,你还可以使用kubectl exec指令,进入到这个Pod当中(即容器的Namespace中)查看这个Volume目录:
$ kubectl exec -it nginx-deployment-5c678cfb6d-lg9lw -- /bin/bash
# ls /usr/share/nginx/html

如果要删除这个Nginx Deployment 的话,直接执行:
$ kubectl delete -f nginx-deployment.yaml
  • 与Kubernetes进行交互尽量选择yaml文件交互;
  • 我们可以使用kubectl create 命令创建一个Pod;
  • 想要获取目前Pod的状态可以使用kubectl get pods命令;
  • 使用kubectl describe pod可以查看某个Pod的详细信息;
  • 如果想要对Pod更新最好使用kubectl apply -f,这样可以做到更加无感的创建Pod或更新;
  • 我们可以使用Volumes来挂载卷;
  • 使用kubectl delete -f可以删除一个Pod。
原文链接:https://www.cnblogs.com/luozhiyun/p/13351499.html,作者:luozhiyun

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK