Skip to content

Commit

Permalink
Allow VIP configuration for single RKE2 node clusters
Browse files Browse the repository at this point in the history
Signed-off-by: Atanas Dinov <[email protected]>
  • Loading branch information
atanasdinov committed Jan 24, 2024
1 parent 7abd7f4 commit 49ca63a
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 22 deletions.
49 changes: 32 additions & 17 deletions pkg/combustion/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ var (
//go:embed templates/15-rke2-multi-node-installer.sh.tpl
rke2MultiNodeInstaller string

//go:embed templates/rke2-ha-api.yaml.tpl
rke2HAAPIManifest string
//go:embed templates/rke2-vip.yaml.tpl
rke2VIPManifest string
)

func configureKubernetes(ctx *image.Context) ([]string, error) {
Expand Down Expand Up @@ -106,13 +106,18 @@ func configureRKE2(ctx *image.Context) (string, error) {
}

func configureSingleNodeRKE2(ctx *image.Context) (string, error) {
zap.S().Info("Configuring single node RKE2 cluster")

serverConfig, err := parseKubernetesConfig(ctx, k8sServerConfigFile)
if err != nil {
return "", fmt.Errorf("parsing RKE2 server config: %w", err)
}

// Establish sane default values
setClusterCNI(serverConfig)
if ctx.ImageDefinition.Kubernetes.Network.APIVIP != "" {
appendClusterTLSSAN(serverConfig, ctx.ImageDefinition.Kubernetes.Network.APIVIP)
}
if ctx.ImageDefinition.Kubernetes.Network.APIHost != "" {
appendClusterTLSSAN(serverConfig, ctx.ImageDefinition.Kubernetes.Network.APIHost)
}
Expand All @@ -127,20 +132,34 @@ func configureSingleNodeRKE2(ctx *image.Context) (string, error) {
return "", fmt.Errorf("downloading RKE2 artefacts: %w", err)
}

var vipManifest string

if ctx.ImageDefinition.Kubernetes.Network.APIVIP == "" {
zap.S().Info("Virtual IP address for RKE2 cluster is not provided and will not be configured")
} else if vipManifest, err = storeRKE2VIPManifest(ctx); err != nil {
return "", fmt.Errorf("storing RKE2 VIP manifest: %w", err)
}

rke2 := struct {
image.Kubernetes
ConfigFile string
InstallPath string
ImagesPath string
VIPManifest string
}{
Kubernetes: ctx.ImageDefinition.Kubernetes,
ConfigFile: k8sServerConfigFile,
InstallPath: installPath,
ImagesPath: imagesPath,
VIPManifest: vipManifest,
}

return storeRKE2Installer(ctx, "single-node-rke2", rke2SingleNodeInstaller, &rke2)
}

func configureMultiNodeRKE2(ctx *image.Context) (string, error) {
zap.S().Info("Configuring multi node RKE2 cluster")

initialiser := findKubernetesInitialiserNode(&ctx.ImageDefinition.Kubernetes)
if initialiser == "" {
return "", fmt.Errorf("failed to determine cluster initialiser")
Expand Down Expand Up @@ -193,29 +212,25 @@ func configureMultiNodeRKE2(ctx *image.Context) (string, error) {
return "", fmt.Errorf("downloading RKE2 artefacts: %w", err)
}

haManifest, err := storeHighAvailabilityRKE2Manifest(ctx)
vipManifest, err := storeRKE2VIPManifest(ctx)
if err != nil {
return "", fmt.Errorf("storing RKE2 HA API manifest: %w", err)
return "", fmt.Errorf("storing RKE2 VIP manifest: %w", err)
}

rke2 := struct {
image.Kubernetes
Initialiser string
InitialiserConfigFile string
HAManifest string
VIPManifest string
InstallPath string
ImagesPath string
APIVIP string
APIHost string
}{
Kubernetes: ctx.ImageDefinition.Kubernetes,
Initialiser: initialiser,
InitialiserConfigFile: initialiserConfigFile,
HAManifest: haManifest,
VIPManifest: vipManifest,
InstallPath: installPath,
ImagesPath: imagesPath,
APIVIP: ctx.ImageDefinition.Kubernetes.Network.APIVIP,
APIHost: ctx.ImageDefinition.Kubernetes.Network.APIHost,
}

return storeRKE2Installer(ctx, "multi-node-rke2", rke2MultiNodeInstaller, &rke2)
Expand Down Expand Up @@ -268,26 +283,26 @@ func findKubernetesInitialiserNode(kubernetes *image.Kubernetes) string {
return ""
}

func storeHighAvailabilityRKE2Manifest(ctx *image.Context) (string, error) {
const haManifest = "rke2-ha-api.yaml"
func storeRKE2VIPManifest(ctx *image.Context) (string, error) {
const vipManifest = "rke2-vip.yaml"

manifest := struct {
APIAddress string
}{
APIAddress: ctx.ImageDefinition.Kubernetes.Network.APIVIP,
}

data, err := template.Parse("rke2-ha-api", rke2HAAPIManifest, &manifest)
data, err := template.Parse("rke2-vip", rke2VIPManifest, &manifest)
if err != nil {
return "", fmt.Errorf("parsing RKE2 HA API template: %w", err)
return "", fmt.Errorf("parsing RKE2 VIP template: %w", err)
}

installScript := filepath.Join(ctx.CombustionDir, haManifest)
installScript := filepath.Join(ctx.CombustionDir, vipManifest)
if err = os.WriteFile(installScript, []byte(data), fileio.NonExecutablePerms); err != nil {
return "", fmt.Errorf("writing RKE2 HA API manifest: %w", err)
return "", fmt.Errorf("writing RKE2 VIP manifest: %w", err)
}

return haManifest, nil
return vipManifest, nil
}

func parseKubernetesConfig(ctx *image.Context, configFile string) (map[string]any, error) {
Expand Down
7 changes: 5 additions & 2 deletions pkg/combustion/kubernetes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ func TestConfigureKubernetes_SuccessfulSingleNodeRKE2Cluster(t *testing.T) {
ctx.ImageDefinition.Kubernetes = image.Kubernetes{
Version: "v1.29.0+rke2r1",
Network: image.Network{
APIVIP: "192.168.122.100",
APIHost: "api.cluster01.hosted.on.edge.suse.com",
},
}
Expand Down Expand Up @@ -166,6 +167,8 @@ func TestConfigureKubernetes_SuccessfulSingleNodeRKE2Cluster(t *testing.T) {
contents := string(b)
assert.Contains(t, contents, "cp server-images/* /var/lib/rancher/rke2/agent/images/")
assert.Contains(t, contents, "cp server.yaml /etc/rancher/rke2/config.yaml")
assert.Contains(t, contents, "cp rke2-vip.yaml /var/lib/rancher/rke2/server/manifests/rke2-vip.yaml")
assert.Contains(t, contents, "echo \"192.168.122.100 api.cluster01.hosted.on.edge.suse.com\" >> /etc/hosts")
assert.Contains(t, contents, "export INSTALL_RKE2_ARTIFACT_PATH=server-installer")
assert.Contains(t, contents, "systemctl enable rke2-server.service")

Expand All @@ -186,7 +189,7 @@ func TestConfigureKubernetes_SuccessfulSingleNodeRKE2Cluster(t *testing.T) {
require.Contains(t, configContents, "cni")
assert.Equal(t, "cilium", configContents["cni"], "default CNI is not set")
assert.Equal(t, nil, configContents["server"])
assert.Equal(t, []any{"api.cluster01.hosted.on.edge.suse.com"}, configContents["tls-san"])
assert.Equal(t, []any{"192.168.122.100", "api.cluster01.hosted.on.edge.suse.com"}, configContents["tls-san"])
}

func TestConfigureKubernetes_SuccessfulMultiNodeRKE2Cluster(t *testing.T) {
Expand Down Expand Up @@ -257,7 +260,7 @@ func TestConfigureKubernetes_SuccessfulMultiNodeRKE2Cluster(t *testing.T) {
assert.Contains(t, contents, "cp server-images/* /var/lib/rancher/rke2/agent/images/")
assert.Contains(t, contents, "cp $CONFIGFILE /etc/rancher/rke2/config.yaml")
assert.Contains(t, contents, "if [ \"$HOSTNAME\" = node1.suse.com ]; then")
assert.Contains(t, contents, "cp rke2-ha-api.yaml /var/lib/rancher/rke2/server/manifests/rke2-ha-api.yaml")
assert.Contains(t, contents, "cp rke2-vip.yaml /var/lib/rancher/rke2/server/manifests/rke2-vip.yaml")
assert.Contains(t, contents, "echo \"192.168.122.100 api.cluster01.hosted.on.edge.suse.com\" >> /etc/hosts")
assert.Contains(t, contents, "export INSTALL_RKE2_ARTIFACT_PATH=server-installer")
assert.Contains(t, contents, "systemctl enable rke2-$NODETYPE.service")
Expand Down
6 changes: 3 additions & 3 deletions pkg/combustion/templates/15-rke2-multi-node-installer.sh.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ if [ "$HOSTNAME" = {{ .Initialiser }} ]; then
CONFIGFILE={{ .InitialiserConfigFile }}

mkdir -p /var/lib/rancher/rke2/server/manifests/
cp {{ .HAManifest }} /var/lib/rancher/rke2/server/manifests/{{ .HAManifest }}
cp {{ .VIPManifest }} /var/lib/rancher/rke2/server/manifests/{{ .VIPManifest }}
fi

umount /var

{{ if .APIHost -}}
echo "{{ .APIVIP }} {{ .APIHost }}" >> /etc/hosts
{{- if .Network.APIHost }}
echo "{{ .Network.APIVIP }} {{ .Network.APIHost }}" >> /etc/hosts
{{- end }}

mkdir -p /etc/rancher/rke2/
Expand Down
9 changes: 9 additions & 0 deletions pkg/combustion/templates/15-rke2-single-node-installer.sh.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@ set -euo pipefail
mount /var
mkdir -p /var/lib/rancher/rke2/agent/images/
cp {{ .ImagesPath }}/* /var/lib/rancher/rke2/agent/images/

{{- if .VIPManifest }}
mkdir -p /var/lib/rancher/rke2/server/manifests/
cp {{ .VIPManifest }} /var/lib/rancher/rke2/server/manifests/{{ .VIPManifest }}
{{- end }}
umount /var

{{- if and .Network.APIVIP .Network.APIHost }}
echo "{{ .Network.APIVIP }} {{ .Network.APIHost }}" >> /etc/hosts
{{- end }}

mkdir -p /etc/rancher/rke2/
cp {{ .ConfigFile }} /etc/rancher/rke2/config.yaml

Expand Down
File renamed without changes.

0 comments on commit 49ca63a

Please sign in to comment.