我的Mall电商实战项目一直在使用Docker有很多朋友建议做容器化部署Kubernetes部署。最近正好在学习。Kubernetes,准备更新一波!今天我们先来学习一下!Kubernetes希望对大家有所帮助!
Kubernetes(简称K8S,KS之间有8个字母)是一个开源系统,用于自动部署、扩展和管理容器应用程序。它将组成应用程序的容器组合成逻辑单元,以便于管理和服务发现。Kubernetes 源自Google 15 年度生产环境运维经验,凝聚了社区最佳创意和实践。
Kubernetes具有如下特性:
- 服务发现与负载平衡:使用不熟悉的服务发现机制,无需修改您的应用程序。
- 存储安排:自动挂载所选存储系统,包括本地存储。
- Secret配置管理:部署更新:Secrets在配置应用程序时,不需要重建容器镜像,也不需要暴露软件堆栈配置中的秘密信息。
- 批量执行:除服务外,Kubernetes也可以管理你的批处理和CI工作负荷,在预期时更换失效容器。
- 水平扩展:使用简单的命令,一个UI或基于CPU应用程序自动扩展。
- 自动在线和回滚:Kubernetes对应用程序或其配置的更改将逐步启动,并监控应用程序的运行状态,以确保您不会同时终止所有实例。
- 自动装箱:根据资源需求等约束自动放置容器,避免影响可用性。
- 自我修复:重新启动失败容器,在节点死亡时更换和调度容器,杀死不响应用户定义的健康检查容器。
Minikube简介
Minikube轻量级Kubernetes可以在本地计算机上创建VM并部署简单的集群,只包含一个节点,Minikube可用于Linux、MacOS和Windows系统。Minikube CLI提供各种指导集群工作的操作,包括启动、停止、检查状态和删除。
Kubernetes核心概念
由于Kubernetes学习他们理解的核心概念很多Kubernetes使用它很有帮助,所以让我们先学习这些核心概念。
Node
Kubernetes集群是指Kubernetes协调高可用计算机集群,每台计算机作为独立单元相互连接。
一个Kubernetes集群包括两种资源:
- Master:负责管理整个集群。协调集群中的所有活动,如调度应用、维护应用所需状态、扩展应用和推出新的更新。
- Node:用于托管正在运行的应用。它可以是虚拟机或物理机,它在Kubernetes集群作为工作机器的作用,每一个Node都有Kubelet,它管理Node而且是Node与Master通信的代理,Node还有处理容器操作的工具,如Docker或rkt。
Deployment
Deployment实例负责创建和更新应用程序。创建Deployment后,Kubernetes Master 将应用程序实例调度到集群中的每个节点。若托管实例的节点关闭或删除,Deployment该实例将被群集中另一个节点上的实例所取代。为解决机器故障维护问题提供了自我修复机制。
可以使用Kubernetes命令行界面Kubectl创建和管理Deployment。Kubectl使用Kubernetes API与集群互动。
Pod
Pod相当于逻辑主机的概念,负责托管应用实例。包括一个或多个应用程序容器(如 Docker),以及一些共享资源(共享存储、网络、运行信息等)。
Service
Service它定义了一组抽象层Pod逻辑集,为此Pod支持外部流量暴露、负载平衡和服务发现。
尽管每个Pod 只有一个IP但如果没有地址Service,这些IP群集外不会暴露。Service允许您的应用程序接收流量。Service也可以用在ServiceSpec标记type暴露的方式,type类型如下:
- ClusterIP(默认):集群内部IP上公开Service。这种类型Service只能从集群中访问。
- NodePort:使用NAT在集群中每个选定Node同一端口公开Service。使用<NodeIP>:<NodePort>外部访问集群Service。是ClusterIP的超集。
- LoadBalancer:在当前云中创建外部负载均衡器(如果支持的话)Service分配一个固定的外部IP。是NodePort的超集。
- ExternalName:通过返回带有该名称的名称CNAME记录,使用任何名称(由spec中的externalName指定)公开Service。不使用代理。
Docker安装
由于Kubernetes操作取决于容器运行时(负责运行容器的软件),现在常用的容器运行时有Docker、containerd和CRI-O。这里选择Docker,先在Linux服务器上安装好Docker环境。
- 安装yum-utils:
yuminstall-yyum-utilsdevice-mapper-persistent-datalvm2
- 为yum源添加docker仓库位置:
yum-config-manager--add-repohttps://download.docker.com/linux/centos/docker-ce.repo
- 安装Docker:
yuminstalldocker-ce
- 启动Docker:
systemctlstartdocker
Minikube安装
- 首先,我们需要下载Minikube并安装二进制安装包:
curl-LOhttps://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 sudoinstallminikube-linux-amd64/usr/local/bin/minikube
- 然后使用以下命令启动Minikube:
minikubestart
- 假如你用的是root用户无法启动并提示以下信息,因为Minikube不允许使用root权限启动需要创建非root账号重启;
*minikubev1.16.0onCentos7.6.1810 *Automaticallyselectedthedockerdriver *The"docker"drivershouldnotbeusedwithrootprivileges. *IfyouarerunningminikubewithinaVM,considerusing--driver=none: *https://minikube.sigs.k8s.io/docs/reference/drivers/none/ XExitingduetoDRV_AS_ROOT:The"docker"drivershouldnotbeusedwithrootprivileges.
- 在这里创造了一个属docker用户组的macro用户,并切换到用户;
#创建用户 useradd-u1024-gdockermacro #设置用户密码 passwdmacro #切换用户 sumacro
- 再次使用minikube start命令启动Minikube,启动成功后,将显示以下信息:
*Topullnewexternalimages,youmayneedt configure a proxy: https://minikube.sigs.k8s.io/docs/reference/networking/proxy/
* Preparing Kubernetes v1.20.0 on Docker 20.10.0 ...
- Generating certificates and keys ...
- Booting up control plane ...
- Configuring RBAC rules ...
* Verifying Kubernetes components...
* Enabled addons: default-storageclass, storage-provisioner
* kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'
* Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
Kubernetes的使用
创建集群
通过Minikube我们可以创建一个单节点的K8S集群,集群管理Master和负责运行应用的Node都部署在此节点上。
- 查看Minikube的版本号:
minikube version
minikube version: v1.16.0
commit: 9f1e482427589ff8451c4723b6ba53bb9742fbb1
- 查看kubectl的版本号,第一次使用会直接安装kubectl:
minikube kubectl version
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.0", GitCommit:"af46c47ce925f4c4ad5cc8d1fca46c7b77d13b38", GitTreeState:"clean", BuildDate:"2020-12-08T17:59:43Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.0", GitCommit:"af46c47ce925f4c4ad5cc8d1fca46c7b77d13b38", GitTreeState:"clean", BuildDate:"2020-12-08T17:51:19Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}
- 如果你想直接使用kubectl命令的话,可以将其复制到/bin目录下去:
# 查找kubectl命令的位置
find / -name kubectl
# 找到之后复制到/bin目录下
cp /mydata/docker/volumes/minikube/_data/lib/minikube/binaries/v1.20.0/kubectl /bin/
# 直接使用kubectl命令
kubectl version
- 查看集群详细信息:
kubectl cluster-info
Kubernetes control plane is running at https://192.168.49.2:8443
KubeDNS is running at https://192.168.49.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
- 查看集群中的所有Node,可以发现Minikube创建了一个单节点的简单集群:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane,master 46m v1.20.0
部署应用
一旦运行了K8S集群,就可以在其上部署容器化应用程序。通过创建Deployment对象,可以指挥K8S如何创建和更新应用程序的实例。
- 指定好应用镜像并创建一个Deployment,这里创建一个Nginx应用:
kubectl create deployment kubernetes-nginx --image=nginx:1.10
- 创建一个Deployment时K8S会产生如下操作:
- 选择一个合适的Node来部署这个应用;
- 将该应用部署到Node上;
- 当应用异常关闭或删除时重新部署应用。
- 查看所有Deployment:
kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-nginx 1/1 1 1 21h
- 我们可以通过kubectl proxy命令创建一个代理,这样就可以通过暴露出来的接口直接访问K8S的API了,这里调用了查询K8S版本的接口;
[macro@linux-local root]$ kubectl proxy
Starting to serve on 127.0.0.1:8001
[root@linux-local ~]# curl http://localhost:8001/version
{
"major": "1",
"minor": "20",
"gitVersion": "v1.20.0",
"gitCommit": "af46c47ce925f4c4ad5cc8d1fca46c7b77d13b38",
"gitTreeState": "clean",
"buildDate": "2020-12-08T17:51:19Z",
"goVersion": "go1.15.5",
"compiler": "gc",
"platform": "linux/amd64"
}
查看应用
通过对运行应用的Pod进行操作,可以查看容器日志,也可以执行容器内部命令。
- 查看K8s中所有Pod的状态:
kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-nginx-78bcc44665-8fnnn 1/1 Running 1 21h
- 查看Pod的详细状态,包括IP地址、占用端口、使用镜像等信息;
kubectl describe pods
Name: kubernetes-nginx-78bcc44665-8fnnn
Namespace: default
Priority: 0
Node: minikube/192.168.49.2
Start Time: Tue, 05 Jan 2021 13:57:46 +0800
Labels: app=kubernetes-nginx
pod-template-hash=78bcc44665
version=v1
Annotations: <none>
Status: Running
IP: 172.17.0.7
IPs:
IP: 172.17.0.7
Controlled By: ReplicaSet/kubernetes-nginx-78bcc44665
Containers:
nginx:
Container ID: docker://31eb1277e507ec4cf8a27b66a9f4f30fb919d17f4cd914c09eb4cfe8322504b2
Image: nginx:1.10
Image ID: docker-pullable://nginx@sha256:6202beb06ea61f44179e02ca965e8e13b961d12640101fca213efbfd145d7575
Port: <none>
Host Port: <none>
State: Running
Started: Wed, 06 Jan 2021 09:22:40 +0800
Last State: Terminated
Reason: Completed
Exit Code: 0
Started: Tue, 05 Jan 2021 14:24:55 +0800
Finished: Tue, 05 Jan 2021 17:32:48 +0800
Ready: True
Restart Count: 1
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-dhr4b (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-dhr4b:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-dhr4b
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events: <none>
- 将Pod的名称设置为环境变量,方便之后使用$POD_NAME来应用Pod的名称:
export POD_NAME=kubernetes-nginx-78bcc44665-8fnnn
- 查看Pod打印的日志:
kubectl logs $POD_NAME
- 使用exec可以在Pod的容器中执行命令,这里使用env命令查看环境变量:
kubectl exec $POD_NAME -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubernetes-nginx-78bcc44665-8fnnn
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
NGINX_VERSION=1.10.3-1~jessie
HOME=/root
- 进入容器内部并执行bash命令,如果想退出容器可以使用exit命令:
kubectl exec -ti $POD_NAME -- bash
公开暴露应用
默认Pod无法被集群外部访问,需要创建Service并暴露端口才能被外部访问。
- 创建一个Service来暴露kubernetes-nginx这个Deployment:
kubectl expose deployment/kubernetes-nginx --type="NodePort" --port 80
- 查看K8S中所有Service的状态:
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5h16m
kubernetes-nginx NodePort 10.105.177.114 <none> 80:31891/TCP 5s
- 查看Service的详情,通过NodePort属性可以得到暴露到外部的端口;
kubectl describe services/kubernetes-nginx
Name: kubernetes-nginx
Namespace: default
Labels: app=kubernetes-nginx
Annotations: <none>
Selector: app=kubernetes-nginx
Type: NodePort
IP Families: <none>
IP: 10.106.227.54
IPs: 10.106.227.54
Port: <unset> 80/TCP
TargetPort: 80/TCP
NodePort: <unset> 30158/TCP
Endpoints: 172.17.0.7:80
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
- 通过CURL命令通过Minikube IP:NodePort IP可以访问Nginx服务,此时将打印Nginx主页信息;
curl $(minikube ip):30158
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
标签的使用
通过给资源添加Label,可以方便地管理资源(如Deployment、Pod、Service等)。
- 查看Deployment中所包含的Label;
kubectl describe deployment
Name: kubernetes-nginx
Namespace: default
CreationTimestamp: Tue, 05 Jan 2021 13:57:46 +0800
Labels: app=kubernetes-nginx
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=kubernetes-nginx
Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
- 通过Label查询Pod:
kubectl get pods -l app=kubernetes-nginx
NAME READY STATUS RESTARTS AGE
kubernetes-nginx-78bcc44665-8fnnn 1/1 Running 1 21h
- 通过Label查询Service:
kubectl get services -l app=kubernetes-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes-nginx NodePort 10.106.227.54 <none> 80:30158/TCP 4m44s
- 给Pod添加Label:
kubectl label pod $POD_NAME version=v1
- 查看Pod的详细信息,可以查看Label信息:
kubectl describe pods $POD_NAME
Name: kubernetes-nginx-78bcc44665-8fnnn
Namespace: default
Priority: 0
Node: minikube/192.168.49.2
Start Time: Tue, 05 Jan 2021 13:57:46 +0800
Labels: app=kubernetes-nginx
pod-template-hash=78bcc44665
version=v1
- 通过Label查询Pod:
kubectl get pods -l version=v1
- 通过Label删除服务:
kubectl delete service -l app=kubernetes-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 30h
可视化管理
Dashboard是基于网页的K8S用户界面。你可以使用Dashboard将容器应用部署到K8S集群中,也可以对容器应用排错,还能管理集群资源。
- 查看Minikube内置插件,默认情况下Dashboard插件未启用:
minikube addons list
|-----------------------------|----------|--------------|
| ADDON NAME | PROFILE | STATUS |
|-----------------------------|----------|--------------|
| dashboard | minikube | disabled |
| default-storageclass | minikube | enabled ✅ |
|-----------------------------|----------|--------------|
- 启用Dashboard插件:
minikube addons enable dashboard
- 开启Dashboard,通过--url参数不会打开管理页面,并可以在控制台获得访问路径:
minikube dashboard --url
* Verifying dashboard health ...
* Launching proxy ...
* Verifying proxy health ...
http://127.0.0.1:44469/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/
- 要想从外部访问Dashboard,需要从使用kubectl设置代理才行,--address设置为你的服务器地址;
kubectl proxy --port=44469 --address='192.168.5.94' --accept-hosts='^.*' &
- 从外部访问服务器需要开启防火墙端口;
# 切换到root用户
su -
# 开启端口
firewall-cmd --zone=public --add-port=44469/tcp --permanent
# 重启防火墙
firewall-cmd --reload
- 通过如下地址即可访问Dashboard:
http://192.168.5.94:44469/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/
- 查看K8S集群中的资源状态信息:
- 通过yaml脚本创建K8S资源:
- 查看K8S中所有Pod的状态信息,通过更多按钮可以查看容器日志和执行内部命令。
当我们的应用需要部署在多个物理机上时,传统的做法是一个个物理机器去部署。如果我们使用了K8S的话,就可以把这些物理机认为是一个集群,只需通过K8S把应用部署到集群即可,无需关心物理机的部署细节。同时K8S提供了水平扩容、自动装箱、自动修复等功能,大大减少了应用集群化部署的工作量。