探索云原生技术之容器编排引擎-Kubernetes/K8S详解(2)

基本理论介绍

什么是云原生

Pivotal公司的Matt Stine于2013年首次提出云原生(Cloud-Native)的概念;2015年,云原生刚推广时,Matt Stine在《迁移到云原生架构》一书中定义了符合云原生架构的几个特征:12因素、微服务、自敏捷架构、基于API协作、扛脆弱性;到了2017年,Matt Stine在接受InfoQ采访时又改了口风,将云原生架构归纳为模块化、可观察、可部署、可测试、可替换、可处理6特质;而Pivotal最新官网对云原生概括为4个要点:DevOps+持续交付+微服务+容器

总而言之,符合云原生架构的应用程序应该是:采用开源堆栈(K8S+Docker)进行容器化,基于微服务架构提高灵活性和可维护性,借助敏捷方法、DevOps支持持续迭代和运维自动化,利用云平台设施实现弹性伸缩、动态调度、优化资源利用率。

此处摘选自《知乎-华为云官方帐号》

在这里插入图片描述

什么是kubernetes

kubernetes,简称K8s,是用8代替8个字符"ubernete"而成的缩写。是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效,Kubernetes提供了应用部署,规划,更新,维护的一种机制

传统的应用部署方式:是通过插件或脚本来安装应用。这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,当然也可以通过创建虚拟机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。

新的部署方式:是通过部署容器方式实现,每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进行迁移。

容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间成一对一关系也使容器有更大优势,使用容器可以在build或release 的阶段,为应用创建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,这使得从研发到测试、生产能提供一致环境。类似地,容器比虚拟机轻量、更"透明",这更便于监控和管理。

Kubernetes是Google开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。在生产环境中部署一个应用程序时,通常要部署该应用的多个实例以便对应用请求进行负载均衡。

在Kubernetes中,我们可以创建多个容器,每个容器里面运行一个应用实例,然后通过内置的负载均衡策略,实现对这一组应用实例的管理、发现、访问,而这些细节都不需要运维人员去进行复杂的手工配置和处理。

此处摘选自《百度百科》

kubernetes核心功能
  • 存储系统挂载(数据卷):pod中容器之间共享数据,可以使用数据卷
  • 应用健康检测:容器内服务可能进程阻塞无法处理请求,可以设置监控检查策略保证应用健壮性
  • 应用实例的复制(实现pod的高可用):pod控制器(deployment)维护着pod副本数量(可以自己进行设置,默认为1),保证一个pod或一组同类的pod数量始终可用,如果pod控制器deployment当前维护的pod数量少于deployment设置的pod数量,则会自动生成一个新的pod,以便数量符合pod控制器,形成高可用。
  • Pod的弹性伸缩:根据设定的指标(比如:cpu利用率)自动缩放pod副本数
  • 服务发现:使用环境变量或者DNS插件保证容器中程序发现pod入口访问地址
  • 负载均衡:一组pod副本分配一个私有的集群IP地址,负载均衡转发请求到后端容器。在集群内部其他pod可通过这个clusterIP访问应用
  • 滚动更新:更新服务不会发生中断,一次更新一个pod,而不是同时删除整个服务。
  • 容器编排:通过文件来部署服务,使得应用程序部署变得更高效
  • 资源监控:node节点组件集成cAdvisor资源收集工具,可通过Heapster汇总整个集群节点资源数据,然后存储到InfluxDb时序数据库,再由Grafana展示。
  • 提供认证和授权:支持角色访问控制(RBAC)认证授权等策略

kubernetes部署服务(实战)

  • 在Kubernetes集群中部署一个Nginx程序,测试下集群是否正常工作。

  • 1:部署Nginx

[root@k8s-master ~]# kubectl create deployment nginx  --image=nginx:1.14-alpine
deployment.apps/nginx created
  • 2:暴露Nginx的80端口,并设置类型为NodePort
[root@k8s-master ~]# kubectl expose deploy nginx --port=80 --target-port=80  --type=NodePort

service/nginx exposed
  • 3:查看服务状态
[root@k8s-master ~]# kubectl get pod,service

NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-6867cdf567-pzl5p   0/1     Pending   0          3m18s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        19h
service/nginx        NodePort    10.102.79.152   <none>        80:30048/TCP   2m47s
  • 4:发现pod一直处于Pending状态。(出问题了)

检查一下pod:

[root@k8s-master ~]# kubectl describe pod nginx-6867cdf567-pzl5p
Name:           nginx-6867cdf567-pzl5p
Namespace:      default
Priority:       0
Node:           <none>
Labels:         app=nginx
                pod-template-hash=6867cdf567
Annotations:    <none>
Status:         Pending
IP:             
IPs:            <none>
Controlled By:  ReplicaSet/nginx-6867cdf567
Containers:
  nginx:
    Image:        nginx:1.14-alpine
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-jqrvp (ro)
Conditions:
  Type           Status
  PodScheduled   False 
Volumes:
  default-token-jqrvp:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-jqrvp
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason            Age        From               Message
  ----     ------            ----       ----               -------
  Warning  FailedScheduling  <unknown>  default-scheduler  0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate.
  Warning  FailedScheduling  <unknown>  default-scheduler  0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate.
  • 5:解决方法(我也是莫名其妙就好了,可以看看下面的文章)

解决方案

  • 6:外网访问Nginx

根据上面kubectl get service,我们可以看到Nginx被映射到外网的端口是30048,所以我们可以这样访问。

  • 注意:一定要通过centos服务器的ip+映射到外网的nginx端口(30048)访问,而不是localhost
[root@k8s-master ~]# curl http://192.168.184.100:30048/
<!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>
  • 我们再来测试一下是否通过从机的ip访问kubernetes集群中的nginx。
[root@k8s-master ~]# curl http://192.168.184.101:30048/
<!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>
  • 结论:我们可以发现,不管是主机ip还是从机ip都可以访问kubernetes集群的nginx。

配置kubernetes中kubectl命令自动补全插件

如果重启机器出现无法自动补全,则执行下面全部source开头的命令即可。其他一概不用动。

  • 1:
yum install -y bash-completion
  • 2:
source /usr/share/bash-completion/bash_completion
  • 3:
source <(kubectl completion bash)
  • 4:
echo “source <(kubectl completion bash)>> ~/.bashrc
  • 5:
vim /root/.bashrc 
  • 6:
source /usr/share/bash-completion/bash_completion
  • 7:
source <(kubectl completion bash)
  • 如何使用:我们在输入kubectl命令时可以用Tab键进行补全。

资源管理

  • 在kubernetes中,一切皆为资源,正如在Java中,一切皆为对象。

  • (deployment,pod,service)等等这些称之为资源。

  • kubernetes实际上就是一个集群,我们可以在kubernetes中部署程序,所谓的部署程序其实就是把程序放到Docker容器中,再将这些Docker容器放到一个个pod中而pod是kubernetes中的最小控制单元kubernetes最底层只能控制pod而不是docker容器),如果需要外部网络(kubernetes集群外的网络)访问到这些pod,那么我们就必须使用到service资源,通过service我们就可以通过pod所在的机器的IP地址+分配到的端口号进行访问

  • 如果kubernetes中的组件(例如pod等等)需要持久化,那么可以使用kubernetes提供的存储服务(例如etcd)。

YAML语法

特点

  • 大小写敏感

  • 缩进表示层级关系

  • 需要表示为同一层级关系的话必须将它们首字母左对齐

  • “#”为注释

  • 一个yaml文件里面写多个yaml配置,可以用 — (三个减号)来分隔。

  • 冒号后面要空格再写值(key: value)

检查yaml语法的网址

yaml文件如下:

# 整形
age: 10
# 布尔型
flag: true
# 实型(浮点型)
price: 123.66
# 日期型
date: 2022-5-14
#字符型
name: 张三
#对象
person:
   age: 20
   name: 李四
#数组
array:
   - 10
   - 20
   - 30

经过转换成JSON格式为如下:

{
  "age": 10,
  "flag": true,
  "price": 123.66,
  "date": "2022-05-14",
  "name": "张三",
  "person": {
    "age": 20,
    "name": "李四"
  },
  "array": [
    10,
    20,
    30
  ]
}
一个小细节
  • 分别在master和slave01、slave02执行:
[root@k8s-master ~]# docker images
...
[root@k8s-slave01 ~]# docker images
...

nginx                                                1.14-alpine         8a2fb25a19f5        3 years ago         16MB
[root@k8s-slave02 ~]# docker images
...
  • 可以看到只有slave01有Nginx:1.14-alpine镜像,这是为什么呢?
  • 此时就牵扯到了kubernetes的执行流程:
    • 因为我们在kubectl执行创建pod(deployment)的时候,请求会先到apiServer,然后通过Scheduler计算将要调度到的某个node工作节点(也就是slave01或者slave02)
    • 再由controller manager去着手安排工作(也就是上面的创建pod/deployment的任务)给Scheduler计算出来的节点执行,这时安排给了slave01,slave01就会去查看本地docker有没有该镜像,如果没有才会从docker hub上面拉取(kubernetes默认是这种机制,可以进行其他设置,比如一直从docker hub上面拉取或者一直从本地拉取这两种机制),这个时候就是只有slave01才有这个nginx镜像了,而正常来说master是没有的,除非手动拉取,因为master节点不会干活,干活的是slave节点。
三种资源管理方式
  • 第二种和第三种都是需要通过执行yaml配置文件来操作kubernetes资源的。而第一种不需要,直接使用命令即可。
第一种:命令式对象管理:只能使用命令去操作kubernetes资源
[root@k8s-master ~]# kubectl run nginx-deployment --image=nginx:1.14-alpine
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/nginx-deployment created

查看一下pod:

[root@k8s-master ~]# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-768546d477-kzvbl   1/1     Running   0          16s

查看一下deployment:

[root@k8s-master ~]# kubectl get deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   1/1     1            1           72s

总结:可以看出kubectl run命令是通过创建deployment(pod控制器)从而创建pod。

第二种:命令式对象配置:指定yaml配置文件来操作kubernetes资源(create(创建)或者patch(更新))
  • create创建操作:

创建yaml配置文件:

vim nginx-pod.yaml

内容如下:如何编写在下面会说。

apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
    name: my-nginx-pod1
    namespace: test
spec:
  containers:
   - image: nginx:1.14-alpine
     name: nginx-containner1
     ports:
      - containerPort: 80

执行命令:

[root@k8s-master ~]# kubectl create -f nginx-pod.yaml 
namespace/test created
pod/my-nginx-pod1 created

查看namespace:

[root@k8s-master ~]# kubectl get namespace
NAME              STATUS   AGE
default           Active   113m
kube-node-lease   Active   113m
kube-public       Active   113m
kube-system       Active   113m
test              Active   37s

进入test的namespace查看pod:

[root@k8s-master ~]# kubectl get pods --namespace=test
NAME            READY   STATUS    RESTARTS   AGE
my-nginx-pod1   1/1     Running   0          100s

查看deployment:

[root@k8s-master ~]# kubectl get deployment
No resources found in default namespace.
[root@k8s-master ~]# kubectl get deployment --namespace=test
No resources found in test namespace.

总结:这种创建pod方式和第一种是完全不一样的,这种方式不是通过创建deployment来创建pod,而是直接创建pod。

用刚刚的yaml文件删除命名空间和pod

[root@k8s-master ~]# kubectl delete -f nginx-pod.yaml
namespace "test" deleted
pod "my-nginx-pod1" deleted

查看pod的详细内容

[root@k8s-master ~]# kubectl describe pods my-nginx-pod1 -n test
Name:         my-nginx-pod1
Namespace:    test
Priority:     0
Node:         k8s-slave02/192.168.184.102
Start Time:   Sun, 15 May 2022 16:56:23 +0800
Labels:       <none>
Annotations:  <none>
Status:       Running
IP:           10.244.2.4
IPs:
  IP:  10.244.2.4
Containers:
  nginx-containner1:
    Container ID:   docker://975f343633f5727105b580bc0b7137513a1db800162538062c503c009f6686d1
    Image:          nginx:1.14-alpine
    Image ID:       docker-pullable://nginx@sha256:485b610fefec7ff6c463ced9623314a04ed67e3945b9c08d7e53a47f6d108dc7
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sun, 15 May 2022 16:56:24 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-x4cbn (ro)

可以看到pod的IP地址和容器镜像等等内容!

集群内访问

[root@k8s-master ~]# curl 10.244.2.4:80
<!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>
第三种:声明式对象配置:指定yaml配置文件来操作kubernetes资源(apply(没有就创建,有就更新))

创建yaml配置文件:

vim nginx-pod-apply.yaml

内容如下:如何编写在下面会说。

apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: Pod
metadata: 
    name: my-nginx-pod-apply1
    namespace: test
spec:
  containers:
   - image: nginx:1.14-alpine
     name: nginx-containner-apply1
     ports:
      - containerPort: 80

执行命令:(由于里面的东西我们原来都没有,所以此时是created新增)

[root@k8s-master ~]# kubectl apply -f nginx-pod-apply.yaml
namespace/test created
pod/my-nginx-pod-apply1 created

查看pod

[root@k8s-master ~]# kubectl get pods -n test
NAME                  READY   STATUS    RESTARTS   AGE
my-nginx-pod-apply1   1/1     Running   0          64s
三种方式使用场景总结
使用场景资源管理方式命令模板
查询资源命令式对象管理kubectl get(describe) 资源名称
新增或者更新资源声明式对象配置kubectl apply -f XXX.yaml
删除资源命令式对象配置kubectl delete -f XXX.yaml

❤️💛🧡本章结束,我们下一章见❤️💛🧡

  • 32
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸鱼打酱油

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值