第22节 sealer 1.9.1新年规划


❤️💕💕记录sealosopen in new window开源项目的学习过程。k8s,docker和云原生的学习open in new window。Myblog:http://nsddd.topopen in new window


[TOC]

准备

时间限制:

0.9.2 发布 - 20230228

截止到 2 月 28 号,两周为期限实现需求,最后一周检查。

所有命令必须以root用户身份运行,目前不支持运行为sudoersrootless

sealer 支持 sudoers

添加一些 e2e 测试案例:

我的任务

  • https://github.com/sealerio/sealer/issues/1999

AFAK,安装 k8s 不一定需要 root 用户,而是具有 root 权限的用户。有些情况下用户不想提供 root 用户,所以我认为 sealer 需要支持这个功能。

sealer不支持没有sudo权限的普通用户安装运行。

目前,sealer 仍然不支持具有 sudo 权限的普通用户。而在未来对sealer进行一些重构之后,我们肯定会支持具有sudo权限的普通用户。

步骤

  1. 确定用户权限要求:需要确定 k8s 安装过程中需要哪些权限,并且需要知道如何在非 root 用户下授予这些权限。
  2. 修改安装脚本和代码:根据用户权限要求,修改安装脚本以确保它能在非 root 用户下正常运行。
  3. 测试安装:在非 root 用户下测试 k8s 安装是否正常。
  4. 更新用户文档:更新 Sealer 用户文档,提供关于非 root 用户安装 k8s 的说明。

解决的问题

文档支持

本文档描述了如何在没有 root 权限的情况下运行 Kubernetes Node 组件,例如 kubelet、CRI、OCI 和 CNI,使用用户命名空间open in new window.

这种技术也称为 rootless mode

解决方案

两种方案 异步开始

  • 跑程序,快速使用非 root 用户过一遍,找出问题所在,跑通就实现了。
  • 过代码,快速过一遍构建部分的代码,找出解决的方案。

跑程序

  • 三台虚拟机

  • 环境:

    root@cubmaster01:~/workspces/sealer/_output/bin/sealer/linux_amd64# source /etc/profile;sealer version
    {"gitVersion":"unknown","gitCommit":"2cd5bb8af","buildDate":"2023-02-03 13:11:59","goVersion":"go1.19.3","compiler":"gc","platform":"linux/amd64"}
    
  • 主机:

    192.168.71.134 node01
    192.168.71.133 node02
    192.168.71.131 master01
    

运行:

sealer run docker.io/sealerio/kubernetes:v1.22.15 \
  --masters 192.168.71.131 \
  --nodes 192.168.71.133,192.168.71.134 --passwd 123456

test

root@cubmaster01:~/workspces# sealer run docker.io/sealerio/kubernetes:v1.22.15   --masters 192.168.71.131   --nodes 192.168.71.133,192.168.71.134 --passwd 123456
Trying to pull docker.io/sealerio/kubernetes:v1.22.15...
Getting image source signatures
Copying blob f5947d538452 skipped: already exists  
Copying blob 570ae92500e2 done  
Copying blob 55f8dfb1b045 done  
Copying blob 8b638286c448 done  
Copying blob 20d88a7b893f done  
Copying blob 7193b0539042 done  
Copying blob 2e3ef0681087 done  
Copying blob c738739a1608 done  
Copying blob bac05865934b done  
Copying config bb75382891 done  
Writing manifest to image destination
Storing signatures
2023-02-03 15:16:25 [INFO] [pull.go:79] bb75382891e7f04f192f1baeab18ef9c9f5503f4de8ac6dfc2a4d94f2164dde6

2023-02-03 15:16:25 [INFO] [run.go:229] start to create new cluster with image: docker.io/sealerio/kubernetes:v1.22.15

2023-02-03 15:16:36 [INFO] [pull.go:79] bb75382891e7f04f192f1baeab18ef9c9f5503f4de8ac6dfc2a4d94f2164dde6

copying files to 192.168.71.134: 31/31 
copying files to 192.168.71.133: 31/31 
+ set -e
+++ dirname /var/lib/sealer/data/my-cluster/rootfs/scripts/docker.sh
++ cd /var/lib/sealer/data/my-cluster/rootfs/scripts
++ pwd
+ scripts_path=/var/lib/sealer/data/my-cluster/rootfs/scripts
+ image_dir=/var/lib/sealer/data/my-cluster/rootfs/scripts/../images
+ DOCKER_VERSION=19.03.15
+ storage=/var/lib/docker
+ mkdir -p /var/lib/docker
+ utils_command_exists docker
+ command -v docker
+ disable_selinux
+ '[' -s /etc/selinux/config ']'
+ systemctl daemon-reload
+ systemctl restart docker.service
+ check_docker_valid
+ docker info
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Docker Buildx (Docker Inc., v0.9.1-docker)
  compose: Docker Compose (Docker Inc., v2.14.1)
  scan: Docker Scan (Docker Inc., v0.23.0)

Server:
 Containers: 34
  Running: 0
  Paused: 0
  Stopped: 34
 Images: 19
 Server Version: 20.10.22
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 5b842e528e99d4d4c1686467debf2bd4b88ecd86
 runc version: v1.1.4-0-g5fd4c4d
 init version: de40ad0
 Security Options:
  apparmor
  seccomp
   Profile: default
 Kernel Version: 5.4.0-137-generic
 Operating System: Ubuntu 20.04.5 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 3.81GiB
 Name: cubmaster01
 ID: YROS:6C7Z:JISN:TGQP:AAGJ:JAOZ:A7XO:3LBP:YJWN:AQIR:TRPC:5ASC
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

WARNING: No swap limit support
++ docker info --format '{{json .ServerVersion}}'
++ tr -d '"'
+ dockerVersion=20.10.22
+ '[' 20.10.22 '!=' 19.03.15 ']'
+ panic 'docker version is 20.10.22, should be 19.03.15, please check'
/var/lib/sealer/data/my-cluster/rootfs/scripts/docker.sh: line 64: panic: command not found
2023-02-03 15:17:25 [INFO] [remove_container.go:66] d400abc92de5308584e6a6e5b06a098698220124ec096b6bbeb3654c2e49bf28

Usage:
  sealer run [flags]

Examples:

run cluster by Clusterfile: 
  sealer run -f Clusterfile

run cluster by CLI flags:
  sealer run docker.io/sealerio/kubernetes:v1.22.15 -m 172.28.80.01 -n 172.28.80.02 -p Sealer123

run app image:
  sealer run localhost/nginx:v1


Flags:
  -f, --Clusterfile string   Clusterfile path to run a Kubernetes cluster
      --apps strings         override default AppNames of clusterimage
      --cmds strings         override default LaunchCmds of clusterimage
  -e, --env strings          set custom environment variables
  -h, --help                 help for run
  -m, --masters string       set count or IPList to masters
      --mode string          load images to the specified registry in advance (default "apply")
  -n, --nodes string         set count or IPList to nodes
  -p, --passwd string        set cloud provider or baremetal server password
      --pk string            set baremetal server private key (default "/root/.ssh/id_rsa")
      --pk-passwd string     set baremetal server private key password
      --port uint16          set the sshd service port number for the server (default port: 22) (default 22)
  -u, --user string          set baremetal server username (default "root")

Global Flags:
      --color string               set the log color mode, the possible values can be [never always] (default "always")      --config string              config file of sealer tool (default is $HOME/.sealer.json)
  -d, --debug                      turn on debug mode
      --hide-path                  hide the log path
      --hide-time                  hide the log time
      --log-to-file                write log message to disk
  -q, --quiet                      silence the usage when fail
      --remote-logger-url string   remote logger url, if not empty, will send log to this url
      --task-name string           task name which will embedded in the remote logger header, only valid when --remote-logger-url is set

2023-02-03 15:17:25 [ERROR] [root.go:75] sealer-unknown: failed to install docker: execute command(bash /var/lib/sealer/data/my-cluster/rootfs/scripts/docker.sh ) on host (192.168.71.131): error(failed to execute command(bash /var/lib/sealer/data/my-cluster/rootfs/scripts/docker.sh ) on host(192.168.71.131): error(exit status 127))

root@cubmaster01:~/workspces# sealer images
REPOSITORY                           TAG        IMAGE ID       CREATED        SIZE
docker.io/sealerio/kubernetes        v1.22.15   bb75382891e7   4 weeks ago    963 MB
docker.io/fanux/ingress-nginx        v1.2.0     d32b3c0b33a8   2 months ago   58.6 KB
localhost/3293172751/ingress-nginx   v1.2.0     d32b3c0b33a8   2 months ago   58.6 KB
root@cubmaster01:~/workspces# kubectl get node
The connection to the server 127.0.0.1:6443 was refused - did you specify the right host or port?
root@cubmaster01:~/workspces# 

遇到的问题,docker版本不符合

也有其他的问题,其他节点不够干净,docker版本不符合,还有docker所有权问题。

sudo chown root:docker /var/run/docker.sock

Ubuntu 22.04 是我的操作系统。在进行广泛研究并浏览大量网站后,我发现以非 root 用户身份运行 Docker 会创建不同的上下文。使用下面列出的命令解决了我的问题。

docker context ls 
docker context use default 

用户可能没有与 docker 守护进程通信的访问权限


2023-02-04 08:51:00 [ERROR] [root.go:75] sealer-unknown: failed to init master0: failed to execute command(kubeadm init --config=/etc/kubernetes/kubeadm.yaml --upload-certs -v 0 --ignore-preflight-errors=SystemVerification,Port-10250,DirAvailable--etc-kubernetes-manifests) on host(192.168.71.131): error(W0204 08:50:55.248878   36042 strict.go:55] error unmarshaling configuration schema.GroupVersionKind{Group:"kubelet.config.k8s.io", Version:"v1beta1", Kind:"KubeletConfiguration"}: error unmarshaling JSON: while decoding JSON: json: unknown field "flushFrequency"
        [WARNING FileExisting-socat]: socat not found in system path
        [WARNING Port-10250]: Port 10250 is in use
error execution phase preflight: [preflight] Some fatal errors occurred:
        [ERROR Port-6443]: Port 6443 is in use
        [ERROR Port-10259]: Port 10259 is in use
        [ERROR Port-10257]: Port 10257 is in use
        [ERROR FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
        [ERROR FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml]: /etc/kubernetes/manifests/kube-controller-manager.yaml already exists
        [ERROR FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml]: /etc/kubernetes/manifests/kube-scheduler.yaml already exists
        [ERROR FileAvailable--etc-kubernetes-manifests-etcd.yaml]: /etc/kubernetes/manifests/etcd.yaml already exists
        [ERROR Port-2379]: Port 2379 is in use
        [ERROR Port-2380]: Port 2380 is in use
        [ERROR DirAvailable--var-lib-etcd]: /var/lib/etcd is not empty
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher
). Please clean and reinstall

清理集群:

sealer delete -a 

rootless

主机:

192.168.71.130 node01
192.168.71.134 node02
192.168.71.133 master01

运行:

sealer run docker.io/sealerio/kubernetes:v1.22.15   --masters 192.168.71.133   --nodes 192.168.71.130,192.168.71.134 --passwd 123456

遇到的问题:

2023-02-04 11:58:21 [ERROR] [root.go:75] sealer-unknown: open /etc/containers/policy.json: permission denied

root.go:75 context

Execute 将所有子命令添加到root命令并适当设置标志。会被 main.main() 调用一次。

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:           "sealer",
	Short:         "A tool to build, share and run any distributed applications.",
	Long:          longRootCmdDescription,
	SilenceUsage:  true,
	SilenceErrors: true,
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := rootCmd.Execute(); err != nil {
		logrus.Errorf("sealer-%s: %v", version.GetSingleVersion(), err)
		os.Exit(1)
	}
}

rootCmd 是一个 cobra 应用程序的根命令,它代表整个应用程序的命令行界面。调用 rootCmd.Execute() 函数将执行整个命令行程序,并执行其中定义的命令和子命令。

安装时候没有权限打开目录

没有权限,我就用权限打开:


目录

文件目的
/etc/shadow保护用户帐户信息
/etc/passwd用户账户信息
/etc/gshadow包含组帐户的阴影信息
/etc/group定义用户所属的组

sudo

test@cubmaster01:/var/lib/dpkg$ sudo sealer run docker.io/sealerio/kubernetes:v1.22.15   --masters 192.168.71.133   --nodes 192.168.71.130,192.168.71.134 --passwd 123456
[sudo] password for test: 
test is not in the sudoers file.  This incident will be reported.

编辑sudoers文件:

即执行:vi /etc/sudoers

找到这行 root ALL=(ALL) ALL,在他下面添加xxx ALL=(ALL) ALL (这里的xxx是你的用户名)

ps:这里说下你可以sudoers添加下面四行中任意一条

youuser ALL=(ALL) ALL
%youuser ALL=(ALL) ALL
youuser ALL=(ALL) NOPASSWD: ALL
%youuser ALL=(ALL) NOPASSWD: ALL
  1. 第一行:允许用户youuser执行sudo命令(需要输入密码).
  2. 第二行:允许用户组youuser里面的用户执行sudo命令(需要输入密码).
  3. 第三行:允许用户youuser执行sudo命令,并且在执行的时候不输入密码.
  4. 第四行:允许用户组youuser里面的用户执行sudo命令,并且在执行的时候不输入密码.

passwd 文件

本地用户信息存储在纯文本/etc/passwd文件中:它的每一行代表一个用户帐户,并且有七个由冒号分隔的字段。

帐户:密码:UID:GID:GECOS:目录:shell

在哪里:

  • *account*是用户名。此字段不能为空。标准 *NIX 命名规则适用。

  • password
    

    是用户密码。

    警告:passwd文件是全球可读的,因此在此文件中存储密码(散列或其他方式)是不安全的。相反,Arch Linux 使用阴影密码open in new window:该password字段将包含一个占位符字符 ( x),表示哈希密码保存在访问受限文件/etc/shadow中。因此,建议始终使用passwd命令更改密码。

  • *UID*是数字用户 ID。在 Arch 中,与服务相对的所谓普通用户的第一个登录名(在 root 之后)默认为 UID 1000;用户的后续 UID 条目应大于 1000。

  • *GID*是用户的数字主要组 ID。GID 的数值列在/etc/groupopen in new window中。

  • *GECOS*是用于信息目的的可选字段;通常它包含完整的用户名,但它也可以由finger等服务使用,并通过chfnopen in new window命令进行管理。此字段是可选的,可以留空。

  • *directory*由登录命令用来设置$HOME环境变量。几个服务用自己的用户使用/,但普通用户一般都设置在一个目录下/home

  • *shell*是用户默认命令 shellopen in new window的路径。该字段是可选的,默认为/bin/bash

myidea

创建一个名为 sealer 的组向其中添加用户。 当 sealer 守护进程(docker daemon)启动时,它会创建一个可由 sealer 组成员访问的 Unix 套接字(Unix socket)。

Warning : docker组拥有和根用户(root user)同等权限。

kk的解决方案:

func (s *SyncKubeConfigToWorker) Execute(runtime connector.Runtime) error {
	if v, ok := s.PipelineCache.Get(common.ClusterStatus); ok {
		cluster := v.(*KubernetesStatus)
		createConfigDirCmd := "mkdir -p /root/.kube"
		if _, err := runtime.GetRunner().SudoCmd(createConfigDirCmd, false); err != nil {
			return errors.Wrap(errors.WithStack(err), "create .kube dir failed")
		}
		syncKubeConfigForRootCmd := fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, "/root/.kube/config")
		if _, err := runtime.GetRunner().SudoCmd(syncKubeConfigForRootCmd, false); err != nil {
			return errors.Wrap(errors.WithStack(err), "sync kube config for root failed")
		}
		userConfigDirCmd := "mkdir -p $HOME/.kube"
		if _, err := runtime.GetRunner().Cmd(userConfigDirCmd, false); err != nil {
			return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
		}
		syncKubeConfigForUserCmd := fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, "$HOME/.kube/config")
		if _, err := runtime.GetRunner().Cmd(syncKubeConfigForUserCmd, false); err != nil {
			return errors.Wrap(errors.WithStack(err), "sync kube config for normal user failed")
		}

		chownKubeConfig := "chown -R (id−u):(id -g) -R $HOME/.kube"
		if _, err := runtime.GetRunner().Cmd(chownKubeConfig, false); err != nil {
		userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false)
		if err != nil {
			return errors.Wrap(errors.WithStack(err), "get user id failed")
		}

		userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false)
		if err != nil {
			return errors.Wrap(errors.WithStack(err), "get user group id failed")
		}

		chownKubeConfig := fmt.Sprintf("chown -R %s:%s -R $HOME/.kube", userId, userGroupId)
		if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false); err != nil {
			return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
		}
	}
	return nil
}

针对问题:sealer version 的版本号问题的解决方案

chown -R 用户名:用户组  目录 

修改用户,使其属于root组:

# 然后修改用户,使其属于root组(wheel),命令如下:
 usermod -g root test

image-20230205112748803

我的思路是安装 sealer 的

sealer 组

Docker 设定一个 docker 组是为了提供一种简便的方法来控制对 Docker 的访问。

通常,使用 Docker 需要 root 权限。但是,开放 root 权限带来的安全风险很大,因此 Docker 引入了一个 docker 组来提高安全性。

这意味着,只有加入 docker 组的用户才能够使用 Docker。可以使用以下命令将用户添加到 docker 组中:

sudo usermod -aG docker $USER
  1. 创建 Sealer 组:使用以下命令创建一个名为 Sealer 的组:

    sudo groupadd Sealer
    
  2. 添加用户:将所有希望具有访问 Kubernetes 集群和镜像的用户添加到 Sealer 组中。使用以下命令添加用户:

    sudo usermod -aG Sealer <username>
    
  3. 设置目录访问权限:将 Kubernetes 集群和镜像的目录的访问权限设置为 Sealer 组,以便 Sealer 组中的用户可以访问。使用以下命令设置目录访问权限:

    sudo chown -R :Sealer <directory>
    sudo chmod -R g+rwx <directory>
    

    其中 <directory> 是要访问的目录,<username> 是要添加到 Sealer 组中的用户的用户名。

如果系统用户需要特定的用户和组 ID,请在创建用户时 使用-u/--uid-g/选项指定它们:--gid

# useradd -r -u 850 -g 850 -s /usr/bin/nologin 用户名

新服务器测试

wget https://github.com/sealerio/sealer/releases/download/v0.9.0/sealer-v0.9.0-linux-amd64.tar.gz && \
tar zxvf sealer-v0.9.0-linux-amd64.tar.gz && sudo mv sealer /usr/bin ; sealer

bug:单节点也需要IP问题

单节点安装提醒:

#sudo sealer run docker.io/sealerio/kubernetes:v1.22.15 
2023-02-05 16:32:44 [ERROR] [root.go:75] sealer-v0.9.0: you must input master ip Or use Clusterfile

#sudo sealer run docker.io/sealerio/kubernetes:v1.22.15 --masters 10.160.25.43

root用户安装单节点:

sealer run docker.io/sealerio/kubernetes:v1.22.15 --masters 10.160.25.43

EEROR:

2023-02-05 16:51:36 [ERROR] [root.go:75] sealer-v0.9.0: failed to execute command(RegistryDomain="sea.hub" RegistryPort="5000" RegistryURL="sea.hub:5000" && cd /var/lib/sealer/data/my-cluster/rootfs/scripts && bash init-registry.sh 5000 /var/lib/sealer/data/my-cluster/rootfs/registry sea.hub) on host(10.160.25.43): error(exit status 1)

给目录和用户权限后:

2023-02-05 21:19:02 [ERROR] [root.go:75] sealer-v0.9.0: cannot mount using driver overlay in rootless mode. You need to run it in a `buildah unshare` session

请给入权限:

sudo echo "sealer ALL=(ALL) ALL" >> /etc/sudoers 

ssh:

 sudo cat >> /etc/hosts <<EOF            
10.0.0.235 master01
10.0.0.236 node01
10.0.0.237 node02
EOF

sealer三台服务器测试:

sealer run docker.io/sealerio/kubernetes:v1.22.15 \
  --masters 10.0.0.235 \
  --nodes 10.0.0.236 10.0.0.237 --passwd Sealer.io@123

error:

2023-02-07 20:08:47 [ERROR] [root.go:75] sealer-v0.9.0: [ssh][110.0.0.236] failed to create ssh session: dial tcp 110.0.0.236:22: i/o timeout

END 链接