由于本人电气出身,对于docker和kubernetes这两个东西可谓是深恶痛绝。然而项目需要,搬砖人只能默默自学了。k3s在自动驾驶中的项目还是很有可取之处的,而且docker也能够避免不同设备之间的系统版本问题。

因为目前的项目都是基于ros2 humble开发的,所以我们所有的节点都是使用ros2进行运行。之前,使用docker进行各个设备之间的数据交换已经完美运行,现在只需要加载到k3s平台就好。其实想想挺简单,然而自我怀疑智商不够的我,加上网上没有找到相关教程,硬生生的花了很多的时间把他啃下来。

两个重要的网站,很多博主都对他进行详细的介绍,可以去查阅他们的总结介绍:

docker

k3s

安装环境:

Ubuntu 22.04

首先需要修改host name, 但不是必要。

hostnamectl set-hostname master

在自己首次搭建环境时,我是已经通过docker网页安装了最新版本的docker engine 25.0.0。 然而它是我在搭建环境中的最大的障碍,后续一直出现错误,提示找不到镜像,我想原因是docker版本对不上。一定要安装rancher给的docker!!!

这是当前k3s版本适应的docker安装脚本:

curl https://releases.rancher.com/install-docker/20.10.sh | sh

根据官网的说明,继续安装k3s:

curl -sfL https://get.k3s.io | sh -s - --docker

结果如下:

root@master:~# kubectl get nodes
NAME     STATUS   ROLES                  AGE   VERSION
master   Ready    control-plane,master   62m   v1.28.5+k3s1

本人用ros2官网的publisher和subscriber的代码作为容器中的节点,作为例子ros2的包命名为my_ros2_package

接下来写一个简单的Dockerfile,并将他放到my_ros2_package的同级目录:

FROM ros:humble

WORKDIR /ros2_workspace

RUN apt-get update && apt-get install -y \
    ros-humble-demo-nodes-cpp vim\
    && rm -rf /var/lib/apt/lists/*
    
COPY . /ros2_workspace/src

RUN . /opt/ros/${ROS_DISTRO}/setup.sh && cd /ros2_workspace && \
    colcon build

CMD ["bash"]

然后将ros包编译成docker的容器镜像:

docker build -t ros2_example:latest -f Dockerfile .

得到以下结果:

root@master:~# docker images
REPOSITORY                         TAG                    IMAGE ID       CREATED          SIZE
ros2_example                       latest                 2637c201e7d1   50 minutes ago   800MB
ros                                humble                 b4f3523df228   3 days ago       752MB

接下来写一个deployment.yaml文件,将ros2_example:latest镜像作为k3s集群中的一个cluster的应用:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ros2-talker
  labels:
    app: ros2-talker
spec:
  selector:
    matchLabels:
      app: ros2-talker
  template:
    metadata:
      labels:
        app: ros2-talker
    spec:
      nodeSelector:
        kubernetes.io/hostname: master
      containers:
        - name: ros2-talker
          image: ros2_example:latest
          command: ["/bin/sh", "-c"]
          args: [". /opt/ros/humble/setup.sh && . install/local_setup.sh && ros2 run my_ros2_package talker"]
          imagePullPolicy: IfNotPresent

这里的imagePullPolicy: IfNotPresent很重要,否则找不到本地的docker镜像,因为它默认是寻找docker Hub的镜像。

kubernetes.io/hostname: master 这里需要和你设备的hostname一致,否则无法将应用添加到k3s集群中去。

sudo kubectl apply -f deployment.yaml

结果如下:

root@master:~# kubectl get pods
NAME                           READY   STATUS    RESTARTS   AGE
ros2-talker-84c4ff4654-x4npj   1/1     Running   0          51m

看到running的状态就表示,环境搭建成功!!!

如果看到pending的状态,那么就是哪里出现问题了,可以通过 kubectl describe pod pod-name 查看节点的运行log,下面是一个示例:

root@master:~# kubectl describe pod ros2-talker-84c4ff4654-x4npj
Name:             ros2-talker-84c4ff4654-x4npj
Namespace:        default
Priority:         0
Service Account:  default
Node:             master/192.168.0.105
Start Time:       Sat, 20 Jan 2024 15:10:46 +0100
Labels:           app=ros2-talker
                  pod-template-hash=84c4ff4654
Annotations:      <none>
Status:           Running
IP:               10.42.0.10
IPs:
  IP:           10.42.0.10
Controlled By:  ReplicaSet/ros2-talker-84c4ff4654
Containers:
  ros2-talker:
    Container ID:  docker://4e2bc1405e1e02fb442122c8e8345e827bab911414cb65852e0b4e35018c206f
    Image:         ros2_example:latest
    Image ID:      docker://sha256:2637c201e7d18098f0597b83997a071fbe1b4591cef614c733e6eec4368d641f
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/sh
      -c
    Args:
      . /opt/ros/humble/setup.sh && . install/local_setup.sh && ros2 run my_ros2_package talker
    State:          Running
      Started:      Sat, 20 Jan 2024 15:10:49 +0100
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bnvvf (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  kube-api-access-bnvvf:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              kubernetes.io/hostname=master
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  53m   default-scheduler  Successfully assigned default/ros2-talker-84c4ff4654-x4npj to master
  Normal  Pulled     53m   kubelet            Container image "ros2_example:latest" already present on machine
  Normal  Created    53m   kubelet            Created container ros2-talker
  Normal  Started    53m   kubelet            Started container ros2-talker

可以通过message来查看哪里出现了问题,并去解决问题。

接下来进入该节点,并管理该节点:

kubectl exec --stdin --tty ros2-talker-84c4ff4654-x4npj -- /bin/bash

进入该节点的容器后,就可以正常查看ros2的topic的信息了。当然,首先需要通过source bash文件加载ros2的环境。

查看最终结果:

root@ros2-talker-84c4ff4654-x4npj:/ros2_workspace# ros2 topic list 
/parameter_events
/rosout
/topic
root@ros2-talker-84c4ff4654-x4npj:/ros2_workspace# ros2 topic echo /topic 
data: 'Hello World: 7056'
---
data: 'Hello World: 7057'
---
data: 'Hello World: 7058'
---
data: 'Hello World: 7059'
---
data: 'Hello World: 7060'
---

到目前为止,搭载k3s的server就完成了。因为该环境不是在国内搭载的,所以使用的安装链接都是官网提供的链接。在其他博客中也看到了更适合在国内使用的链接,大家可以参考他们的链接。

由于设备原因,目前无法在第二台终端安装k3s agent,并实现listener节点在agent运行。因为ros2的通信在不同设备中的docker出现了很多问题,希望k3s的ros2通信能够顺利实现。该篇有时间会后续发布。

本人第一次写博客,记录一下自己在打怪路上的一些心得,希望也能够对别人有帮助。不足之处可以提出建议。