K8S搭建docker本地镜像仓库

私有仓库最常用的有Registry、Harbor两种。Registry是docker官方的项目,Harbor是VMware公司开源的企业级Docker Registry项目。

一、Docker Harbor

1、Docker Harbor概述:
有可视化的Web管理界面,可以方便管理Docker镜像,又提供了多个项目的镜像权限管理及控制功能。
2、Harbor的优势:

1>. 基于角色控制
2>. 基于镜像的复制策略
3>. 支持LDAP/AD
4>. 图像删除和垃圾收集
5>. 图像UI
6>. 审计
7>. RESTful API

3、 Harbor知识点

1>. Proxy:通过一个前置的反向代理统一接收浏览器、Docker客户端的请求,并将请求转发给后端不同的服务
2>. Registry:负责存储Docker镜像,并处理docker push/pull命令
3>. Core services:Harbor的核心功能,包括UI、webhook、token服务
4>. Database:为core services提供数据库服务
5>. Log collector:负责收集其他组件的log,供日后进行分析

4、Docker私有仓库架构
20210329194412952.jpg
如上图所示:
所有的请求都经过proxy代理,proxy代理转发给Core services和Registry,其中Core services包括UI界面、token令牌和webhook网页服务功能,Registry主要提供镜像存储功能。如果要进行下载上传镜像,要经过token令牌验证然后从Registry获取或上传镜像,每一次下载或上传都会生成日志记录,会记入Log collector,而用户身份权限及一些镜像语言信息会被存储在Database中。
5、Harbor构建Docker私有仓库
1>. 环境配置:
server:CentOS7.9 10.100.2.33 docker-v20.10.8、docker-compose-v1.29.2、harbor-offline-v2.3.2
client:CentOS7.9 10.100.2.34 docker-v20.10.8
2>. 部署Harbor服务
Harbor 被部署为多个 Docker 容器,因此可以部署在任何支持 Docker 的 Linux 发行版上。服务端主机需要安装 Python、Docker 和 Docker Compose。
1) 官方下载地址:
harbor:https://github.com/goharbor/harbor/releases/download/v2.3.2/harbor-offline-installer-v2.3.2.tgz
docker-compose:https://github.com/docker/compose/releases/download/1.29.2/docker-compose-Linux-x86_64
2) 安装docker:
在线安装:

yum install yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 注:docker官方源:yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce
systemctl enable docker --now

离线安装:

在线下载RPM包:
yum install yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yumdownloader --resolve --destdir /root/docker_rpm docker-ce
或:yum install --downloadonly --downloaddir /root/docker_rpm docker-ce
上传RPM包到离线环境安装:
yum install /root/docker_rpm/*.rpm
systemctl enable docker --now

3) 安装docker-compose和准备harbor:
安装docker-compose:

cp docker-compose-Linux-x86_64 /usr/bin/docker-compose
chmod +x /usr/bin/docker-compose
或使用yum安装:yum install docker-compose

安装harbor:

tar zxvf harbor-offline-installer-v2.3.2.tgz -C /usr/local/
cd /usr/local/harbor/
cp harbor.yml.tmpl harbor.yml
vim harbor.yml
hostname: reg.k8stest.com
http:
  port: 80
https:
  port: 443
  certificate: /usr/local/harbor/ssl/harbor.crt
  private_key: /usr/local/harbor/ssl/harbor.key
data_volume: /usr/local/harbor/data
harbor_admin_password: Harbor12345
mkdir ssl data

4) 生成证书
可以使用其他CA服务器颁发证书,也可以使用本机生成自签名证书。

使用自签名证书
cd /etc/pki/CA/
touch index.txt && echo 01> serial
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=harbor-server" -days 3650 -out ca.crt
openssl genrsa -out harbor.key 2048
openssl req -new -key harbor.key -subj "/CN=harbor-server" -out harbor.csr
openssl x509 -req -in harbor.csr -CA ca.crt  -CAkey ca.key -CAcreateserial -out harbor.crt -days 3650
拷贝证书到/usr/local/harbor/ssl目录
cp harbor.key harbor.crt /usr/local/harbor/ssl/

5) 安装harbor

cd /usr/local/harbor/
./install.sh
docker-compose ps

Xshell_20210910232447.jpg
Habor 服务启停:
注意:如果harbor.yml配置修改了,要先执行"./prepare"命令进行配置载入,然后再重启harbor服务。

查看Habror:docker-compose ps
启动Harbor:docker-compose start
停止Harbor:docker-compose stop
重启Harbor:docker-compose restart
另外:Harbor还可以通过down和up命令去停止和启动,只不过这种方式是删除、创建的关停和启动。
docker-compose down -v
docker-compose up -d
注1:
执行此命令时必须cd到项目的根目录下("cd /usr/local/harbor/"),或者指定docker-compose.yml文件:
docker-compose -f /usr/local/harbor/docker-compose.yml ps
否则提示如下错误:
ERROR: 
  Can't find a suitable configuration file in this directory or any parent. Are you in the right directory?
  Supported filenames: docker-compose.yml, docker-compose.yaml, compose.yml, compose.yaml
注2:
在服务器重启时,harbor的服务会有启动失败的情况,提示:"Exited (137)"
通过 docker logs registry 看不到有用的日志信息。
通过 docker inspect registry 查看container状态:
"State": {
    "Status": "exited",
    "Running": false,
    "Paused": false,
    "Restarting": false,
    "OOMKilled": false,
    "Dead": false,
    "Pid": 0,
    "ExitCode": 137,
    "Error": "failed to initialize logging driver: dial tcp [::1]:1514: connect: connection refused",
    "StartedAt": "2021-09-25T07:13:09.167745719Z",
    "FinishedAt": "2021-09-25T07:21:30.770117401Z",
    "Health": {
        "Status": "unhealthy",
        "FailingStreak": 0,
        ...
}
可以看到Error错误提示,原因是:日志服务未先启动,而其它服务需要先到日志服务器注册,所以会造成端口访问拒绝。
解决办法:注册harbor服务,重启服务器harbor服务也能正常启动了。

注册harbor服务:

vim /usr/lib/systemd/system/harbor.service
  [Unit]
  Description=Harbor
  After=docker.service systemd-networkd.service systemd-resolved.service
  Requires=docker.service
  Documentation=http://github.com/vmware/harbor
  
  [Service]
  Type=simple
  Restart=on-failure
  RestartSec=5
  ExecStart=/usr/bin/docker-compose -f /usr/local/harbor/docker-compose.yml up
  ExecStop=/usr/bin/docker-compose -f /usr/local/harbor/docker-compose.yml down
  
  [Install]
  WantedBy=multi-user.target
允许开机自启动,查看harbor状态,所有服务状态正常。
systemctl enable harbor --now
systemctl status harbor

Xshell_20210925175601.jpg
6) 访问Harbor
修改windows客户端的hosts文件:
10.100.2.33 reg.k8stest.com
打开浏览器,输入自定义域名:https://reg.k8stest.com 即可打开页面。
chrome_20210910232914.jpg
输入用户名:admin,密码登录(密码在harbor.yml中定义)。
chrome_20210910233023.jpg
可以创建项目、用户、仓库等。例如创建一个私有的testproj项目,用于上传镜像。
chrome_20210910233204.jpg
7) 配置服务端daemon.json文件

mkdir /etc/docker
vim /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "insecure-registries": ["reg.k8stest.com"],
  "registry-mirrors": 
  [
    "https://pee6w651.mirror.aliyuncs.com",
    "http://hub-mirror.c.163.com",
    "https://docker.mirrors.ustc.edu.cn",
    "http://f1361db2.m.daocloud.io",
    "https://registry.docker-cn.com"
  ]
}
vim /etc/hosts
  10.100.2.33 reg.k8stest.com
systemctl restart docker

8) 镜像管理

登录镜像仓库
docker login -u admin https://reg.k8stest.com
docker logout
docker login -u admin http://reg.k8stest.com
下载镜像(内网环境可以直接上传)
docker pull ubuntu
docker tag ubuntu:latest reg.k8stest.com/testproj/ubuntu:v1
docker images |grep k8stest
docker login http://reg.k8stest.com
docker push reg.k8stest.com/testproj/ubuntu

Xshell_20210911001523.jpg
Xshell_20210911005102.jpg
在控制台可以看到刚上传的镜像。
chrome_20210911005230.jpg
9) 客户端访问
客户端访问和本地访问差不多。
编辑docker的daemon.json文件:
该版本的harbor默认使用的https协议,如没有证书或为自签证书,则需使用"insecure-registries"字段,将harbor访问域名加入其中。

mkdir /etc/docker
vim /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "insecure-registries": ["reg.k8stest.com"],
  "registry-mirrors": ["http://reg.k8stest.com"]
}
注:"insecure-registries"参数也可以放在docker启动文件上:
vim /usr/lib/systemd/system/docker.service
修改启动项:ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
为ExecStart=/usr/bin/dockerd -H fd:// --insecure-registry reg.mytest.com --containerd=/run/containerd/containerd.sock
systemctl start docker
vim /etc/hosts
  10.100.2.33 reg.k8stest.com

上传下载镜像

docker login http://reg.k8stest.com
docker pull reg.k8stest.com/testproj/ubuntu:v1
docker tag reg.k8stest.com/testproj/ubuntu:v1 reg.k8stest.com/testproj/ubuntu:v2
docker push reg.k8stest.com/testproj/ubuntu:v2
docker tag nginx:latest reg.k8stest.com/testproj/nginx:v2
docker push reg.k8stest.com/testproj/nginx:v2

Xshell_20210911010538.jpg
Xshell_20210911011438.jpg
在控制台查看操作日志:
chrome_20210911011524.jpg

二、Docker Registry

三、如何在K8S中使用私有镜像库

前言:
  在企业落地 K8S 的过程中,私有镜像库 (专用镜像库) 必不可少,特别是在 Docker Hub 开始对免费用户限流之后, 越发的体现了搭建私有镜像库的重要性。
  私有镜像库不但可以加速镜像的拉取还可以避免因特有的"网络问题"导致镜像拉取失败尴尬。
  当然部署了私有镜像库之后也需要对镜像库设置一些安全策略,大部分私有镜像库采用 IP访问策略+认证 (非公开项目) 的方式对镜像库进行安全保护。
  那么对于含有认证限制的镜像库,在 K8S 中该如何优雅的集成呢?
  下文就总结了在 K8S 中使用私有镜像库的几种情况和方式。
1>. 在 K8S 中使用私有镜像库
  首先要确定私有镜像库的授权使用方式,在针对不同的使用方式选择对应的认证配置。
1) 针对节点 (Node):
  这个应该是企业使用 K8S 时最常用的方式,一般也只要使用这个就够了,并且该方案几乎是使用了私有镜像库之后必不可少的配置,它可以做到:
  <1>. 在节点环境中进行一定的配置,不需要在 K8S 中进行其它的配置即可享有具体私有库的权限。
  <2>. 该方案对该节点上的所有 Pods 生效,同时还对非 Pods 镜像生效,例如: kubelet 的 pause 镜像,这个非常关键。
2) 针对服务账号 (ServiceAccount)、针对命名空间 (Namespace):
  配置了该 ServiceAccount 的 Pod 都享有这个 ServiceAccount 所配置的镜像库认证设置。
  还可以利用 K8S 中 default ServiceAccount 机制,达到对一个具体命名空间中没有特殊设置的所有 Pod 生效。
3) 针对 Pod:
  针对具体的 Pod 进行认证配置,该 Pod 就会具有私有库的权限。
  Deployment、DaemonSet、StatefulSet、CronJob、Job 等资源都使用了PodTemplate 最终都会以具体的 Pod 资源体验,所以在 PodTemplate 中配置也算对 Pod 配置。
2>. 配置步骤
前提条件:
  1. 一个可用私有镜像库 (可用采用 Harbor 搭建)
  2. 私有镜像库的账号和密码 (推荐只给只读权限)
  3. CRI 基于 Docker (其它的 CRI 暂没有验证)
1) 针对节点 (Node) 配置
  1. 编写 Docker 配置文件
  2. 将 Docker 配置文件放在指定位置
  3. 重启 kubelet
  <1>. 编写 Docker 配置文件
    首先编写 Docker 的认证配置文件, 格式如下:

{
  "auths": {
    "<HOST>": {
      "auth": "<BASIC_AUTHORIZATION>"
    }
  }
}
注:
    <HOST> # 为私有镜像库的地址, 例如: hub.docker.com
    <BASIC_AUTHORIZATION> # 为 BASE64(<USERNAME>:<PASSWORD>)
    例如:
      cmVhZGVyOjEyMzQ1Ng==,其中账号是:reader,密码是:123456
    使用:拼接后进行 base64
完整的配置文件,例如:
{
  "auths": {
    "hub.docker.com": {
      "auth": "cmVhZGVyOjEyMzQ1Ng=="
    },
    "harbor.domain.cn": {
      "auth": "cmVhZGVyOiFAIzQ1Ng=="
    }
  }
}
如有多个镜像库在 auths 节中进行添加即可。

  <2>. 将 Docker 配置文件放在指定位置

推荐放在 kubelet 根目录中,配置文件需以 config.json 命名。
  默认的 kubelet 根目录一般为 /var/lib/kubelet (如有修改进行替换即可),也就是需要放置在 /var/lib/kubelet/config.json。
还可以放在以下位置:
    {--root-dir:-/var/lib/kubelet}/config.json
    {cwd of kubelet}/config.json
    ${HOME}/.docker/config.json
    /.docker/config.json
    {--root-dir:-/var/lib/kubelet}/.dockercfg
    {cwd of kubelet}/.dockercfg
    ${HOME}/.dockercfg
    /.dockercfg
参考文档:
  https://kubernetes.io/zh/docs/concepts/containers/images/
  https://kubernetes.io/docs/concepts/containers/images/#configuring-nodes-to-authenticate-to-a-private-registry
注意:
  放在 ${HOME} 开头的位置,需要在 kubelet service 环境中配置 HOME 的路径,不然不会生效。例如:HOME=/root
    下面是使用 kubeadm 安装的环境中可用的脚本,如果不是请自行配置。
      echo "HOME=${HOME}" >> /var/lib/kubelet/kubeadm-flags.env

  <3>. 重启 kubelet

  如果 init 不是 systemd,请自行替换服务重启的命令
    systemctl daemon-reload; systemctl restart kubelet

2) 针对服务账号 (ServiceAccount)、针对命名空间 (Namespace)
  1. 创建一个 Docker Registry Secret资源
  2. 设置 ServiceAccount 的 imagePullSecrets
  3. 将 Pod 的 serviceAccountName 设置为该 ServiceAccount 的名称
  <1>. 创建一个 Docker Registry Secret资源

使用 kubectl cli 创建Registry Secret资源:
    kubectl create secret docker-registry <SECRET_NAME> --docker-server=<DOCKER_REGISTRY_SERVER> --docker-username=<DOCKER_USER> --docker-password=<DOCKER_PASSWORD> -n <NAMESPACE>
    其中:
        <SECRET_NAME>     # 是Secret资源的名称, 在编辑 SA 资源的时需要引用
        <DOCKER_REGISTRY_SERVER> # 是私有镜像库的服务器地址
        <DOCKER_USER>     # 是私有镜像库认证的账号
        <DOCKER_PASSWORD>         # 是私有镜像库认证的密码
        <NAMESPACE>     # 是命名空间名称
    示例命令如下:
      kubectl create secret docker-registry docker-reader-secret --docker-server=harbor.domain.cn --docker-username=reader --docker-password=123456 -n basic
使用 yaml 创建Registry Secret资源:
    cat docker-reader-secret.yaml
      apiVersion: v1
      data:
        .dockerconfigjson: eyJhdXRocyI6eyJET0NLRVJfUkVHSVNUUllfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImF1dGgiOiJSRTlEUzBWU1gxVlRSVkk2UkU5RFMwVlNYMUJCVTFOWFQxSkUifX19
      kind: Secret
      metadata:
        name: docker-reader-secret 
        namespace: default
      type: kubernetes.io/dockerconfigjson
      其中:
          .dockerconfigjson 是base64之后的字符串,具体内容参考 "编写 Docker 配置文件" 节中的内容。
            https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
    kubectl apply -f docker-reader-secret.yaml

  <2>. 设置 ServiceAccount 的 imagePullSecrets

apiVersion: v1
kind: ServiceAccount
metadata:
  name: service1
  namespace: basic
secrets:
- name: service1-token-mp4qs
imagePullSecrets:
- name: docker-reader-secret

  <3>. 将资源的 serviceAccountName 设置为该 ServiceAccount 的名称

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
      serviceAccountName: service1

  <4>. 如何针对命名空间内的所有Pod?

K8S 中有个默认的机制,会在命名空间中创建一个名称为 default 的 ServiceAccount (sa) 资源。
并且在资源没有单独指定 serviceAccountName 时, 默认使用 default 作为serviceAccountName。
所以我们只需设置 default ServiceAccount 的 imagePullSecrets 即可对该命名空间中没有特殊指定 serviceAccountName 字段的 Pod 生效了。

3) 针对 Pod
  1. 创建一个 Docker Registry Secret资源
  2. 设置 Pod 的 imagePullSecrets
  <1>. 创建一个 Docker Registry Secret资源
    参考 "创建一个 Docker Registry Secret资源" 节中的内容
  <2>. 设置 Pod 的 imagePullSecrets

一个具体的 Pod
    apiVersion: v1
    kind: Pod
    metadata:
      name: foo
      namespace: awesomeapps
    spec:
      containers:
        - name: foo
          image: janedoe/awesomeapp:v1
      imagePullSecrets:
        - name: docker-reader-secret
针对具有 PodTemplate 内容的资源
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.14.2
          imagePullSecrets:
          - name: docker-reader-secret

相关文章

发表新评论