macOS工作室¶
在 macOS工作室起步 我思考了不同的构建工作室的基础环境,例如虚拟化和容器化。我个人一直在不同的Linux环境和macOS环境中切换(有太多的设备和安装部署),每次起步初始化确实也花费了不少时间。例如我有机会能短暂使用 Apple ARM架构芯片M1 Pro ,但是很快又得切换回 Arch Linux 的 MacBook Pro 15” Late 2013 。
理想的工作方式是全面采用容器化技术( Docker Atlas )来构建,并结合 kind(本地docker模拟k8s集群) 模拟 Kubernetes Atlas ,这样在不同的工作环境中,只要采用合适的镜像( 从Dockerfile构建Docker镜像 )以及基础运行环境,就能够无缝切换。
Homebrew¶
要实现完整的可移植工作环境(和 Linux Atlas 对齐),在macOS环境中使用 Homebrew 来构建基础环境:
安装 homebrew :
通过网络安装Homebrew¶
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
安装必要工具:
在macOS新系统必装的brew软件¶
brew update
brew install vim tmux tree webp gawk gsed openconnect nginx
brew install --cask iterm2
brew install --cask docker
brew install golang
切换python3版本:
切换macOS的python3版本到homebrew提供的版本¶
cd /opt/homebrew/bin
ln -s python3.11 python3
ln -s python3.11 python
ln -s pip3.11 pip3
ln -s pip3.11 pip
Python virtualenv 和 Sphinx文档¶
结合 Sphinx文档 同时安装和部署好 Python virtualenv Python Atlas 开发环境
虚拟沙箱环境非常简单:
venv初始化¶
cd ~
python3 -m venv venv3
激活:
激活venv¶
source venv3/bin/active
安装Sphinx 以及 rtd :
通过virtualenv的Python环境安装sphinx doc¶
pip install sphinx
pip install sphinx_rtd_theme
pip install sphinxnotes-strike
# 支持视频、YouTube和中文搜索,安装组件和配置
Kubernetes Atlas 模拟¶
通过 Homebrew macOS安装Docker :
通过Homebrew安装Docker Desktop for macOS¶
brew install --cask docker
在macOS平台上安装kind¶
brew install kind kubectl
3个管控节点,5个工作节点的集群,并且结合本地registry,采用 kind集群本地Registry 方法
kind-with-registry-macos.sh
脚本:
运行Registry适配kind集群(dev),macOS环境的Docker Desktop for macOS¶
#!/bin/sh
set -o errexit
CLUSTER_NAME='dev'
# create registry container unless it already exists
reg_name="${CLUSTER_NAME}-registry"
reg_port='5001'
if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then
docker run \
-d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \
registry:2
fi
# create a cluster with the local registry enabled in containerd
cat <<EOF | kind create cluster --name ${CLUSTER_NAME} --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
- role: worker
- role: worker
- role: worker
- role: worker
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"]
endpoint = ["http://${reg_name}:5000"]
EOF
# connect the registry to the cluster network if not already connected
if [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}' "${reg_name}")" = 'null' ]; then
docker network connect "kind" "${reg_name}"
fi
# Document the local registry
# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: local-registry-hosting
namespace: kube-public
data:
localRegistryHosting.v1: |
host: "localhost:${reg_port}"
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
EOF
需要 修复kind集群重启异常 ,所以再执行:
通过 kind_static_ips.sh 脚本设置kind集群每个node静态IP¶
#!/usr/bin/env bash
set -e
CLUSTER_NAME='dev'
reg_name="${CLUSTER_NAME}-registry"
# Workaround for https://github.com/kubernetes-sigs/kind/issues/2045
# all_nodes=$(kind get nodes --name "${CLUSTER_NAME}" | tr "\n" " ")
# 我将 registry 也加入了列表指定静态IP
all_nodes=$(kind get nodes --name "${CLUSTER_NAME}" | tr "\n" " ")${reg_name}
declare -A nodes_table
ip_template="{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}"
echo "Saving original IPs from nodes"
for node in ${all_nodes}; do
#nodes_table["${node}"]=$(docker inspect -f "${ip_template}" "${node}")
#registry有2个网络接口,这里采用了一个比较ugly的方法,过滤掉不属于kind网络的接口IP
nodes_table["${node}"]=$(docker inspect -f "${ip_template}" "${node}" | sed 's/172.17.0.2//')
echo "${node}: ${nodes_table["${node}"]}"
done
echo "Stopping all nodes and registry"
docker stop ${all_nodes} >/dev/null
echo "Re-creating network with user defined subnet"
subnet=$(docker network inspect -f "{{(index .IPAM.Config 0).Subnet}}" "kind")
echo "Subnet: ${subnet}"
gateway=$(docker network inspect -f "{{(index .IPAM.Config 0).Gateway}}" "kind")
echo "Gateway: ${gateway}"
docker network rm "kind" >/dev/null
docker network create --driver bridge --subnet ${subnet} --gateway ${gateway} "kind" >/dev/null
echo "Assigning static IPs to nodes"
for node in "${!nodes_table[@]}"; do
docker network connect --ip ${nodes_table["${node}"]} "kind" "${node}"
echo "Assigning IP ${nodes_table["${node}"]} to node ${node}"
done
echo "Starting all nodes and registry"
docker start ${all_nodes} >/dev/null
echo -n "Wait until all nodes are ready "
while :; do
#[[ $(kubectl get nodes | grep Ready | wc -l) -eq ${#nodes_table[@]} ]] && break
#需要启动的k8s节点比docker的容器列表少2 (registry和haproxy没有包含在k8s)
pod_num=`expr ${#nodes_table[@]} - 2`
[[ $(kubectl get nodes | grep Ready | wc -l) -eq ${pod_num} ]] && break
echo -n "."
sleep 5
done
echo