简易DOCKER/K8S使用心得

news/2024/7/8 7:20:18 标签: docker, centos, 运维

1. DOCKER安装

1.1 前置环境

首先,如果使用CentOS,你至少需要7.4以上。从内核角度来说,建议使用8.2及以上。
如果是7.4以下的版本,可以通过设置仓库到7.4以上版本,再

yum install centos-release kernel
#实际上安装了kernel就可以了,这步可以不做
yum upgrade 

进行版本升级。

此外,还至少需要以下依赖:

yum install -y yum-utils device-mapper-persistent-data lvm2

dockerce_16">1.2.docker-ce安装

由于一些众所周知的原因,不能用docker EE,一般建议社区版docker CE

#默认的海外地址,建议用aliyun的加速地址
#yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce -y

docker_26">1.3. 配置docker

创建或修改此文件 /etc/docker/daemon.json

{
  "registry-mirrors": ["https://xxx.mirror.aliyuncs.com"], //阿里云申请账户时候给的加速地址
  "insecure-registries": ["10.35.9.161"], //可能的私有仓库
  "log-opts": {"max-size":"64m", "max-file":"3"}
}

部分环境存在/etc/systemd/system/docker.service,可能存在–insecure-registries,会发生冲突,删除字段即可。

配置完后即可启动docker

service docker start
docker login registry.cn-hangzhou.aliyuncs.com -u your_account -p your_passwd

2. 生成DOCKER

2.1 简易镜像生成法

首先需要准备一份Dockerfile

FROM hub.docker.com/centos/centos:7.5.1804
COPY myapp/ /opt/myapp/
CMD ["/opt/myapp/start.sh"]

以上述为例,FROM表示基础镜像。
COPY为需要增加文件到DOCKER中的具体位置
CMD为默认命令行

然后就可以生成了

docker build -t hub.my.com/mycomp/myapp:1.0 .

生成完毕后,我们可以上传到仓库当中,注意tag时的version,可以和我们build时不一致;push时需要和tag一致,表示最终上传这个tag。

TAG=`docker images | grep myapp | grep 1.0 | awk {'print $3'} | head -n 1`
docker tag $TAG hub.my.com/mycomp/myapp:1.0
docker push hub.my.com/mycomp/myapp:1.0

2.2 高阶镜像玩法

实际生产过程中,我们可能需要基于标准镜像,准备两份版本。一份包含了完整的编译环境,一份为生产环境运行使用。这样我们就可以在任意部署了docker 的机器上进行三方编译工作,不再依赖编译的宿主机。
以下面的Dockerfile为例,直接用编译镜像生成文件,并直接在生产镜像中应用,制作成运行镜像。

FROM hub.my.com/mycomp/centos78_devel:1.0 AS BUILDS
COPY . /opt/code/mysrc
RUN cd /opt/code/mysrc && ./build.sh

FROM hub.my.com/mycomp/centos78_release:1.0
COPY --from=BUILDS /opt/code/mysrc/dist /opt/myapp
CMD ["/opt/myapp/bin/start_in_docker.sh"]

为了加速源码目录的COPY动作,可以在需要的目录下,设置文件.dockerignore

.svn
**/*.d

3. 调试DOCKER

以上命令表示以HOST模式(直接拥有真机地址)运行镜像。网络模式这里就不展开讨论了。

docker run -it --net=host hub.my.com/mycomp/myapp:1.0
#运行后,可以用ps查看当前正在运行的容器,并通过exec进入该容器
docker ps
docker exec -it 00eeaa6467cc /bin/bash

以下也是一种利用编译镜像编译的办法。
即通过-v参数将本地磁盘的当前路径,映射到docker内的/opt/code目录,并通过-w参数指定该目录为运行目录。
通过-e参数将版本号作为环境变量REVISION,实现自动标记版本号。
和上面的方法的区别在于中间产物会遗留在真实硬盘上,减少复制的成本,方便试错

docker run --rm -it -v $(pwd):/opt/code/ -w /opt/code/ -e REVISION=${REVISION} hub.hitry.io/hitry/centos78_devel:1.0 ./build.sh

4. yaml的一些编写技巧

由于我们是使用了Rancher+K8S的方案,因此对于从机来说,直接按命令运行就行了,K8S的部署就不展开了。
本段开始,都是基于K8S/Rancher来说的。

4.1 活用环境变量的fieldRef

对应在Rancher中就是Field,目前只有这些信息可以获取,复杂的就需要K8SAPI了

名称含义
metadata.namePOD名称,有状态服务时很有用
metadata.namespace服务命名空间
metadata.uidUID
spec.nodeName宿主机HostName
spec.serviceAccountNameserviceAccount名
status.hostIP宿主机IP
status.podIPPOD IP
status.podIPsPOD IP列表

4.2 活用亲和性和反亲和性

4.2.1 利用亲和性设置启动节点

我们可以为每个物理节点打上标签,然后利用亲和性,我们可以指定期望在哪台机器上运行服务。甚至可以结合DaemonSet保证所有的期望节点都跑一遍(虽然不推荐这么干)。

例如:
我们期望最好(可以不是)这个服务在main_node上运行,必须在gpu_node上运行,且不允许在inner_node上运行。如果使用rancher,这个有界面可以配。

spec:
  template:
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - preference:
              matchExpressions:
              - key: main_node
                operator: In
                values:
                - "true"
            weight: 100
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: gpu_node
                operator: In
                values:
                - "true"
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: inner_node
                operator: NotIn
                values:
                - "true"

4.2.2 利用反亲和性实现应用互斥或最多每机一实例

在rancher中并不提供反亲和性的图形化配置,不过可以手工修改yaml支持此K8S的特性
比较典型的一个应用场景是我希望某个服务(特别是网络类型为HOST模式的)最多每台机器起一份,避免端口冲突,或GPU使用冲突。

以流媒体服务为例,其存在大范围UDP端口段监听,必然使用HOST模式。我也不需要使用DaemonSet方式每机起一份加大问题定位的复杂度,可能只需要双机热备,或按需扩容。因此,正常使用时,只要保证运行的实例数量小于节点数量即可;但是当部分节点瘫痪,使得实例数大于节点数时,就需要阻塞那些多出来的实例,把他们挂起,不要拥挤到同一台机器跑起来。

此时可以这样处理:

  1. 为该服务分配一个标签,key为app,value为mediasvr
spec:
  template:
    metadata:
      labels:
        app: mediasvr
  1. 设置反亲和性,不允许在已经有app=mediasvr标签的机器上运行(不同的服务都设置key=app,是并行存在的,如果你想A服务和B服务互斥,也可以用相同的办法)
spec:
  template:
    spec:
      affinity:
		podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - mediasvr
            topologyKey: kubernetes.io/hostname

5. K8SAPI

在某些情况下,我们需要更为复杂的操作,可以使用K8S的API进行复杂查询

K8S API v1.20

调用K8S的API需要的token,基本有两种方法:

  1. 使用你本身的serviceaccount进行查询。但是需要注意的是默认的default账户权限很低,很多操作需要自定义账户并提权。
  2. 可以创建一个公用的API Key,并将Bearer Token保存下来(比方说放置到config map中,让具体的服务通过环境变量引用得知)。在rancher中,操作流程为:
    在这里插入图片描述
    “右上角下拉”-> “API & Keys” -> “添加Key”-> “选择作用范围到指定集群”
    *注意:不选择作用范围,这个key只能调用rancher的API,选择了集群,则会自动在K8S中创建账户

5.1 利用K8S API 获取所有节点的IP列表

举个实际的例子,当一个HOST类型的服务,启动了某个内部通讯用的监听,我并不想让外部来连接,需要一个IP白名单。在传统的方案中,只能依靠部署人员手工配置,或者直接网络隔离(防火墙/NAT等)。
利用K8S的API,我们可以轻易的得知所有服务节点清单,以配置白名单。

curl -H "Authorization: Bearer $token" -X GET -H 'Accept: application/json' -H 'Content-Type: application/json' --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://127.0.0.1:6443/api/v1/nodes > nodes.json

需要注意的事项:
1)$token就是上面说的Bearer Token
2)如果不是HOST模式,那么请求的地址就不能是127.0.0.1,而是上面提到的status.hostIP中获取到的宿主机IP。
3)CA证书可以不指定,设置成允许非安全连接也能用。

此时拿到的是一个很长的json。我们可以使用一个简易的Python或者其他语言来解析他。

python fetch_ip.py nodes.json > whitelist.conf
#!/usrbin/env python

import json
import string
import httplib,sys

if __name__ == '__main__' :
    if len( sys.argv ) < 2 :
        print "Please run like this: python fetch_ip.py <filePath>"

    f = open(sys.argv[1],'r');
    rootnode = json.load(f)
    for item in rootnode["items"]:
        for addr in item["status"]["addresses"]:
            if addr["type"] == "InternalIP":
                print addr["address"]

5.2 利用K8S API 获取指定服务的POD列表

还是以之前的mediasvr为例。当某些场景下,我希望获取所有的mediasvr清单。
可以利用设置标签+labelSelector进行筛选。本质上来说你找的是拥有这个标签的POD,不是这个服务名的。

curl -H "Authorization: Bearer $token" -X GET -H 'Accept: application/json' -H 'Content-Type: application/json' --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://127.0.0.1:6443/api/v1/namespaces/default/pods?labelSelector=app%3Dmediasvr

http://www.niftyadmin.cn/n/1335555.html

相关文章

动画---分块运动

动画---分块运动 package com.example.test;import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.gra…

爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!

1 前言近期&#xff0c;有些朋友问我一些关于如何应对反爬虫的问题。由于好多朋友都在问&#xff0c;因此决定写一篇此类的博客。把我知道的一些方法&#xff0c;分享给大家。博主属于小菜级别&#xff0c;玩爬虫也完全是处于兴趣爱好&#xff0c;如有不足之处&#xff0c;还望…

组件prop检验

Vue.js中的父子组件相信都已经是大家很常用到的功能了&#xff0c; 父组件通过props属性向子组件传值子组件通过自定义事件向父组件传值 那么我们怎么去校验props属性中的类型呢 笔者列出以下几种方法&#xff1a; 1&#xff1a;直接检测 如果将 string 换成Number 那么在控制台…

网上下载文档需要付费?试试这几招,老师傅一般都会使用

平时在上网找资料时候&#xff0c;当发现下载时候需要付费&#xff0c;我们一般该怎么办呢&#xff1f;扎心啦老铁&#xff0c;难道你就甘心放弃现在找到的文档资料&#xff1f; 其实不用的啦&#xff01;这里为大家汇总了几个下载文档的方法&#xff0c;大家如果有什么需要下…

也谈GB28181码流收发

1.前置文章 PS封装格式&#xff1a;GB28181协议RTP传输 H265的国标PS流打包 这两篇文章里面有的就不细说了 2.发送的规则细节 在国标中&#xff0c;不需要对H264/H265裸流进行进一步的去NAL等操作&#xff0c;直接发裸流即可。如果一个包发不下&#xff0c;可以分包发送&a…

教你把多个视频合并成一个视频的方法

前几天朋友向我请教视频合并的方法&#xff0c;而说起视频合并相信大部分小伙伴都听说过&#xff0c;但是当中也有部分小伙伴不知道怎么合并视频&#xff08;多个视频合并成一个视频&#xff09;。下面就来教大家用迅捷视频转换器把多个视频合并成一个视频的方法。 第一步&…

查询浏览器是否支持html5

js判断 插入js代码 <script> window.onload function() { if (window.applicationCache) { alert("你的浏览器支持HTML5"); } else { alert("你的浏览器不支持HTML5"); } } </script> 2原生标签兼容 <body> <canvas style"bac…

【转】自定义修改Nginx的server

nginx版本暴露会留下不少麻烦&#xff1b;索性一不做二不休&#xff0c;名字也改掉。 1 修改server要在编译Nginx修改/src/core/nginx.h文件 #define NGINX_VERSION "1.20" #define NGINX_VER "mywebserver" 2 修改src/http/ngx_http_header_…