Bootstrap container for openstack provider (capo)

This patchset provides the Go code and scripts for the
Bootstrap container for Openstack.

The Bootstrap container for Openstack provider accepts
three commands: create, delete and help.
- create - creates an Ephemeral K8S cluster in Openstack
- delete - deletes the Ephemeral K8S cluster in Openstack
- help - Stdout the help text for usage of the bootstrap container.

Documentation is available at bootstrap_capo/README.md

Change-Id: Idd444834070b84170f18561626c487e23a3ca951
This commit is contained in:
Ratnopam Chakrabarti 2020-08-28 00:09:35 -04:00
parent 32374c3293
commit 3b351b1aa1
18 changed files with 881 additions and 0 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ bootstrap_capg/go.mod
bootstrap_capz/.vscode/launch.json bootstrap_capz/.vscode/launch.json
bootstrap_capz/go.mod bootstrap_capz/go.mod
bootstrap_capz/go.sum bootstrap_capz/go.sum
bootstrap_capo/capo-ephemeral

66
bootstrap_capo/Dockerfile Normal file
View File

@ -0,0 +1,66 @@
# Copyright 2018 AT&T Intellectual Property. All other rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
ARG GO_IMAGE=golang:1.14.4
ARG PYTHON_IMAGE=python:3.8
FROM ${GO_IMAGE} as builder
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
WORKDIR /home/build
COPY main.go go.mod go.sum ./
COPY config/ config/
COPY resource/ resource/
RUN go install /home/build
RUN go build -o capo-ephemeral /home/build
FROM ${PYTHON_IMAGE}
LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc://#airshipit@freenode' \
org.opencontainers.image.url='https://airshipit.org' \
org.opencontainers.image.source='https://opendev.org/airship/images' \
org.opencontainers.image.vendor='The Airship Authors' \
org.opencontainers.image.licenses='Apache-2.0'
RUN set -ex && \
pip install python-openstackclient
RUN set -ex && \
apt-get update
RUN useradd -m bootstrap
USER bootstrap
WORKDIR /home/bootstrap
ENV HOME=/home/bootstrap
ENV PATH="${PATH}:${HOME}"
# Copy the binary from builder
COPY --from=builder /home/build/capo-ephemeral .
# Copy resources including scripts and help.txt file
COPY resource/* $HOME/
# Executes the go application capo-ephemeral
CMD ["capo-ephemeral"]

55
bootstrap_capo/Makefile Normal file
View File

@ -0,0 +1,55 @@
SHELL := /bin/bash
PUSH_IMAGE ?= false
DOCKER_MAKE_TARGET := build
# docker image options
DOCKER_REGISTRY ?= quay.io
DOCKER_FORCE_CLEAN ?= true
DOCKER_IMAGE_NAME ?= capo-ephemeral
DOCKER_IMAGE_PREFIX ?= airshipit
DOCKER_IMAGE_TAG ?= latest
DOCKER_IMAGE ?= $(DOCKER_REGISTRY)/$(DOCKER_IMAGE_PREFIX)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)
DOCKER_TARGET_STAGE ?= release
CONTAINER_TEMP = capo-ephemeral-temp
.PHONY: all
all: build docker
.PHONY: images
images: build docker
.PHONY: build
build: main.go go.mod go.sum config/openstack_cluster.go config/openstack_config.go Dockerfile
@docker build --target builder --network=host \
--build-arg MAKE_TARGET=$(DOCKER_MAKE_TARGET) \
--tag $(DOCKER_IMAGE) .
docker run --name $(CONTAINER_TEMP) $(DOCKER_IMAGE) /bin/true
docker cp $(CONTAINER_TEMP):/home/build/capo-ephemeral .
.PHONY: docker
docker: capo-ephemeral resource/create-k8s-cluster.sh resource/delete-k8s-cluster.sh resource/user-data.sh resource/help.txt Dockerfile
@docker build . --network=host \
--build-arg MAKE_TARGET=$(DOCKER_MAKE_TARGET) \
--tag $(DOCKER_IMAGE) \
--force-rm=$(DOCKER_FORCE_CLEAN)
ifeq ($(PUSH_IMAGE), true)
docker push $(DOCKER_IMAGE)
endif
.PHONY: clean
clean:
@rm capo-ephemeral
.PHONY: lint
lint:
@echo TODO
# style checks
.PHONY: tests
tests: images
sudo rm -f $(HELP_FILE)
cp openstack-config.yaml /tmp
docker run -v /tmp:/kube --env-file bootstrap-env.list --name capo-bootstrap-test $(DOCKER_IMAGE)

102
bootstrap_capo/README.md Normal file
View File

@ -0,0 +1,102 @@
# Openstack Bootstrap Container
This project contains the Go application as well as the shell scripts and configuration files for
implementing the Openstack Bootstrap container.
The Openstack Bootstrap container is responsible to create or delete a Kubernetes (K8S) cluster on
Openstack. The K8S cluster is created using `kubeadm`.
## Go Application
The Go application is the container orchestrator that is responsible for translating commands
into actions: create, delete, help.
The Go application reads the Ephemeral cluster configuration file (e.g., openstack-config.yaml) and
converts the attributes into environment variables. These environment variables are used by the
shell scripts to create or delete the K8S cluster.
To build this Go application, execute the following commands:
```bash
go install .
go build -o capo-ephemeral
```
## Shell Scripts
The shell scripts make use of openstack cli commands to create and delete K8S cluster.
The other alternative that was considered was to use magnum container orchestration APIs.
In order to keep things generic, openstack cli command was chosen to create and delete the K8S
cluster.
### Create K8S Cluster script
The **create-k8s-cluster.sh** script creates a K8S cluster using the information provided in
the Ephemeral cluster configuration file. It passes `user-data.sh` script in the
`openstack server create` command to execute series of steps to initiate creation of the K8S
cluster at boot time. Once the cluster is created, its **kubeconfig** file is copied to the
container's volume mount, "sharing" it with the host.
### Delete K8S Cluster script
The **delete-k8s-cluster.sh** script deletes the underlying VM and the K8S cluster using the
information provided in the Ephemeral cluster configuration file.
## Dockerfile
The **Dockerfile** is used to build the Openstack Bootstrap container image.
Execute the following command to build the Bootstrap container image:
```bash
make docker
```
## Pre-requisite
- [Devstack](https://docs.openstack.org/devstack/latest/guides/devstack-with-lbaas-v2.html)
is installed.
- The most recent version of the *64-bit amd64-arch QCOW2* image for *Ubuntu 18.04* is used for
creating the ephemeral cluster.
The image is available
[here](https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img) for
download and should be available in the devstack environment.
- `~/.airship/` directory on host machine contains `clouds.yaml` and `openstack-config.yaml` files.
- airship configuration file is updated with `ephemeral` cluster configuration information.
## Appendix
### Required Configuration
#### Ephemeral Cluster Configuration
```bash
$ cat openstack-config.yaml
apiVersion: v1
kind: OpenstackCloudConfig
metadata:
name: capi-openstack
credentials:
credential: clouds.yaml
cloudName: devstack
spec:
cluster:
machineSize: ds4G
kubeconfig: capo.kubeconfig
securityGroup: bootstrap-sec-grp
```
#### Airship Configuration
```bash
$ cat ~/.airship/config
apiVersion: airshipit.org/v1alpha1
bootstrapInfo:
ephemeral:
container:
image: quay.io/airshipit/capo-bootstrap:latest
name: capo-bootstrap
volume: /home/stack/.airship:/kube
ephemeralCluster:
config: openstack-config.yaml
```

View File

@ -0,0 +1,3 @@
BOOTSTRAP_COMMAND=help
BOOTSTRAP_CONFIG=openstack-config.yaml
BOOTSTRAP_VOLUME=/tmp:/kube

View File

@ -0,0 +1,13 @@
clouds:
devstack:
auth:
auth_url: "http://10.0.1.4/identity"
password: pass
project_domain_id: default
project_name: demo
user_domain_id: default
username: demo
identity_api_version: "3"
region_name: RegionOne
volume_api_version: "3"

View File

@ -0,0 +1,104 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config
import (
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
)
const (
// Bootstrap container environment variables
openstackCredential = "OS_CREDENTIAL_FILE"
openstackSecurityGroup = "OS_SECURITY_GROUP"
openstackCloudName = "OS_CLOUD"
openstackMachineSize = "OS_MACHINE_FLAVOR"
openstackKubeconfigFile = "OS_KUBECONFIG_FILE"
bootstrapHelpFile = "help.txt"
// BootstrapCommand environment variable
bootstrapHome = "SRC_DIR"
bootstrapVolumeSep = ":"
)
// SetOpenstackCloudEnvVars sets the environment variables used by the script
func SetOpenstackCloudEnvVars(config *OpenstackConfig) error {
err := os.Setenv(openstackCredential, config.Credentials.Credential)
err = os.Setenv(openstackCloudName, config.Credentials.CloudName)
err = os.Setenv(openstackSecurityGroup, config.Spec.Cluster.SecurityGroup)
err = os.Setenv(openstackMachineSize, config.Spec.Cluster.MachineSize)
err = os.Setenv(openstackKubeconfigFile, config.Spec.Cluster.Kubeconfig)
if err != nil {
return err
}
return nil
}
// GetVolumeMountPoints extracts the source and destination of a volume mount
func GetVolumeMountPoints(volumeMount string) (string, string, error) {
if len(volumeMount) == 0 {
return "", "", errors.New("volume mount is mandatory, please provide volume mount")
}
sepPos := strings.Index(volumeMount, bootstrapVolumeSep)
srcMountPoint := volumeMount[:sepPos]
dstMountPoint := volumeMount[sepPos+1:]
return srcMountPoint, dstMountPoint, nil
}
// CreateOSCluster creates the ephemeral K8S cluster in Openstack
func CreateOSCluster() error {
srcDir := os.Getenv(bootstrapHome)
shellScriptFile := "./create-k8s-cluster.sh"
shellScript := filepath.Join(srcDir, shellScriptFile)
return execute(shellScript)
}
// DeleteOSCluster deletes the ephemeral K8S cluster in Openstack
func DeleteOSCluster() error {
srcDir := os.Getenv(bootstrapHome)
shellScriptFile := "./delete-k8s-cluster.sh"
shellScript := filepath.Join(srcDir, shellScriptFile)
return execute(shellScript)
}
func execute(shellScript string) error {
cmd := exec.Command(shellScript)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
log.Printf("Executing script %s\n", shellScript)
if err := cmd.Start(); err != nil {
return err
}
return cmd.Wait()
}
// HelpOSCluster prints the help information to supplement the creation of K8S ephemeral cluster
func HelpOSCluster() error {
srcDir := os.Getenv(bootstrapHome)
src := filepath.Join(srcDir, bootstrapHelpFile)
b, err := ioutil.ReadFile(src)
fmt.Fprintln(os.Stdout, string(b))
return err
}

View File

@ -0,0 +1,82 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config
import (
"io/ioutil"
"log"
"sigs.k8s.io/yaml"
)
// OpenstackConfig holds configurations for bootstrap steps
type OpenstackConfig struct {
// +optional
Kind string `yaml:"kind,omitempty"`
// +optional
APIVersion string `yaml:"apiVersion,omitempty"`
// Configuration parameters for metadata
Metadata *Metadata `yaml:"metadata"`
// Configuration parameters for metadata
Credentials *Credentials `yaml:"credentials"`
// Configuration parameters for spec
Spec *Spec `yaml:"spec"`
}
// Metadata structure provides the cluster name to assign and labels to the k8s cluster
type Metadata struct {
Name string `yaml:"name"`
Labels []string `yaml:"labels,omitempty"`
}
// Credentials structu provides the credentials to authenticate with Azure Cloud
type Credentials struct {
Credential string `yaml:"credential"`
CloudName string `yaml:"cloudName"`
}
// Spec structure contains the info for the ck8s luster to deploy
type Spec struct {
Cluster Cluster `yaml:"cluster"`
}
// Cluster struct provides data for the k8s cluster to deploy
type Cluster struct {
// flavor of VM
MachineSize string `yaml:"machineSize,omitempty"`
// Kubeconfig filename to save
Kubeconfig string `yaml:"kubeconfig,omitempty"`
// security group
SecurityGroup string `yaml:"securityGroup,omitempty"`
}
// ReadYAMLFile reads YAML-formatted configuration file and
// de-serializes it to a given object
func ReadYAMLFile(filePath string, cfg *OpenstackConfig) error {
data, err := ioutil.ReadFile(filePath)
log.Printf("Attempting to read Openstack bootstrap cluster configuration file at '%s'", filePath)
if err != nil {
return err
}
return yaml.Unmarshal(data, cfg)
}

8
bootstrap_capo/go.mod Normal file
View File

@ -0,0 +1,8 @@
module capo
go 1.14
require (
github.com/pkg/errors v0.9.1
sigs.k8s.io/yaml v1.2.0
)

8
bootstrap_capo/go.sum Normal file
View File

@ -0,0 +1,8 @@
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

85
bootstrap_capo/main.go Normal file
View File

@ -0,0 +1,85 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"capo/config"
"log"
"os"
"flag"
)
const (
createCmd = "create"
deleteCmd = "delete"
helpCmd = "help"
)
func main() {
var configPath string
flag.StringVar(&configPath, "c", "", "Path for the Openstack Cloud bootstrap configuration (yaml) file")
flag.Parse()
volMount := os.Getenv("BOOTSTRAP_VOLUME")
_, dstMount, err := config.GetVolumeMountPoints(volMount)
if err != nil {
log.Printf("Failed to get volume mount, please provide volume mount")
os.Exit(1)
}
openstackConfigPath := dstMount + "/" + os.Getenv("BOOTSTRAP_CONFIG")
if len(configPath) == 0 {
configPath = openstackConfigPath
}
configYAML := config.OpenstackConfig{}
err = config.ReadYAMLFile(configPath, &configYAML)
if err != nil {
log.Printf("Failed to load Openstack Cloud Bootstrap config file")
os.Exit(2)
}
err = config.SetOpenstackCloudEnvVars(&configYAML)
if err != nil {
log.Printf("Failed to set Openstack Cloud environment variables")
os.Exit(3)
}
command := os.Getenv("BOOTSTRAP_COMMAND")
switch {
case command == createCmd:
err = config.CreateOSCluster()
if err != nil {
os.Exit(4)
}
case command == deleteCmd:
err = config.DeleteOSCluster()
if err != nil {
os.Exit(5)
}
case command == helpCmd:
err = config.HelpOSCluster()
if err != nil {
os.Exit(6)
}
default:
log.Printf("The --command parameter value shall be 'create', 'delete' or 'help'")
os.Exit(7)
}
os.Exit(0)
}

View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: OpenstackCloudConfig
metadata:
name: capi-openstack
credentials:
credential: clouds.yaml
cloudName: devstack
spec:
cluster:
machineSize: ds4G
kubeconfig: capo.kubeconfig
securityGroup: bootstrap-sec-grp

View File

@ -0,0 +1,144 @@
#!/bin/bash
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Bootstrap Environment Variables MUST be provided when running the Container
echo "Checking that Openstack Cloud Name has been provided ..."
if [[ -z "$OS_CLOUD" ]]; then
echo "Openstack cloud name MUST be provided."
exit 1
else
echo "OS_CLOUD = $OS_CLOUD"
fi
echo "Checking that Openstack Cloud Configuration has been provided ..."
if [[ -z "$OS_CREDENTIAL_FILE" ]]; then
echo "Openstack Cloud Configuration MUST be provided."
exit 1
else
echo "OS_CREDENTIAL_FILE = $OS_CREDENTIAL_FILE"
fi
echo ""
echo "Checking Environment Variables used by the Bootstrap Container ..."
if [[ -z "$OS_MACHINE_FLAVOR" ]]; then
echo "Assigning default value for OS_MACHINE_FLAVOR"
export OS_MACHINE_FLAVOR="ds2G"
fi
if [[ -z "$OS_KUBECONFIG_FILE" ]]; then
echo "Assigning default value for OS_KUBECONFIG_FILE"
export OS_KUBECONFIG_FILE="kubeconfig"
fi
if [[ -z "$OS_SECURITY_GROUP" ]]; then
echo "Assigning default value for OS_SECURITY_GROUP"
export OS_SECURITY_GROUP="bootstrap-mgmt-sec-grp"
fi
cp /kube/"$OS_CREDENTIAL_FILE" ~
echo "OS_CLOUD = $OS_CLOUD"
echo "OS_CREDENTIAL_FILE = $OS_CREDENTIAL_FILE"
echo "OS_MACHINE_FLAVOR = $OS_MACHINE_FLAVOR"
echo "OS_KUBECONFIG_FILE = $OS_KUBECONFIG_FILE"
echo "OS_SECURITY_GROUP = $OS_SECURITY_GROUP"
echo ""
echo ""
echo "creating envs"
export SECURITY_GROUP=$OS_SECURITY_GROUP
export CAPI_VM="bootstrap-k8s"
export OS_USERNAME=admin
echo "listing all active images"
openstack image list
echo "SECURITY_GROUP = $SECURITY_GROUP"
echo "VM NAME = $CAPI_VM"
#echo "creating security group"
openstack security group create --project demo --project-domain Default $SECURITY_GROUP
#echo "adding rules to the security group"
openstack security group rule create $SECURITY_GROUP --protocol tcp --remote-ip 0.0.0.0/0
openstack security group rule create $SECURITY_GROUP --protocol tcp --dst-port 10248:10252 --remote-ip 0.0.0.0/0
export PRIVATE_NETWORK_ID=$(openstack network show private | grep "\<id\>" | awk '{print $4}' )
export K8S_IMAGE_ID=$(openstack image list | grep "ubuntu-k8s" | awk '{print $2}' )
echo "PRIVATE_NW_ID = $PRIVATE_NETWORK_ID"
echo "K8S_IMAGE = $K8S_IMAGE_ID"
#Generate ssh key pair without being prompted for pass phrase
ssh-keygen -f ~/.ssh/id_rsa -t rsa -N ''
echo "printing public key"
echo $(cat ~/.ssh/id_rsa.pub)
export SSH_KEY_PUB=$(cat ~/.ssh/id_rsa.pub)
echo $SSH_KEY_PUB > stack.pub
openstack keypair delete stack
echo "creating openstack key pair"
openstack keypair create --public-key stack.pub stack
echo "************** listing key pairs ***************"
openstack keypair list
export FLOATING_IP_ADDRESS=${FLOATING_IP_ADDRESS:-172.24.4.199}
echo "Add floating IP to public network"
openstack floating ip create public --floating-ip-address $FLOATING_IP_ADDRESS
echo "creating vm for spinning up ephemeral kubernetes cluster"
openstack server create --image $K8S_IMAGE_ID --flavor $OS_MACHINE_FLAVOR --security-group $SECURITY_GROUP --nic net-id=$PRIVATE_NETWORK_ID \
--key-name stack --user-data user-data.sh $CAPI_VM --wait
echo "associating floating ip with vm"
openstack server add floating ip $CAPI_VM $FLOATING_IP_ADDRESS
echo "waiting for kubernets cluster to be up"
#echo "check if kube config is ready on remote vm"
N=0
MAX_RETRY=30
DELAY=60
until [ "$N" -ge ${MAX_RETRY} ]
do
if ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa ubuntu@$FLOATING_IP_ADDRESS '[ -d /home/ubuntu/.kube/ ]'; then
printf "kube config is available\n"
break
else
printf "Kube config does not exist, or still being created\n"
N=$((N+1))
echo "$N: Retry to check if kubeconfig exists"
sleep ${DELAY}
fi
done
echo "copying the kubeconfig of ephemeral cluster to container host"
scp -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa ubuntu@$FLOATING_IP_ADDRESS:/home/ubuntu/.kube/config /kube/$OS_KUBECONFIG_FILE
chmod +rw /kube/$OS_KUBECONFIG_FILE
echo "done copying kubeconfig file"
echo "*************** done ***************"

View File

@ -0,0 +1,80 @@
#!/bin/bash
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Bootstrap Environment Variables MUST be provided when running the Container
echo "Checking that Openstack Cloud Name has been provided ..."
if [[ -z "$OS_CLOUD" ]]; then
echo "Openstack cloud name MUST be provided."
exit 1
else
echo "OS_CLOUD = $OS_CLOUD"
fi
echo "Checking that Openstack Cloud Configuration has been provided ..."
if [[ -z "$OS_CREDENTIAL_FILE" ]]; then
echo "Openstack Cloud Configuration MUST be provided."
exit 1
else
echo "OS_CREDENTIAL_FILE = $OS_CREDENTIAL_FILE"
fi
cp /kube/$OS_CREDENTIAL_FILE ~
echo "deleting the k8s ephemeral cluster"
if [[ -z "$OS_KUBECONFIG_FILE" ]]; then
echo "Assigning default value for OS_KUBECONFIG_FILE"
export OS_KUBECONFIG_FILE="kubeconfig"
fi
if [[ -z "$OS_SECURITY_GROUP" ]]; then
echo "Assigning default value for OS_SECURITY_GROUP"
export OS_SECURITY_GROUP="bootstrap-mgmt-sec-grp"
fi
export SECURITY_GROUP=$OS_SECURITY_GROUP
export CAPI_VM="bootstrap-k8s"
export FLOATING_IP_ADDRESS=${FLOATING_IP_ADDRESS:-172.24.4.199}
echo "OS_CLOUD = $OS_CLOUD"
echo "OS_CREDENTIAL_FILE = $OS_CREDENTIAL_FILE"
echo "OS_MACHINE_FLAVOR = $OS_MACHINE_FLAVOR"
echo "OS_KUBECONFIG_FILE = $OS_KUBECONFIG_FILE"
echo "OS_SECURITY_GROUP = $OS_SECURITY_GROUP"
echo ""
echo ""
openstack server delete $CAPI_VM --wait
if [ $? -ne 0 ]; then
echo "*** Failed to delete cluster in VM $CAPI_VM "
exit 1
fi
echo "K8s cluster deleted successfully in VM $CAPI_VM"
openstack security group delete $SECURITY_GROUP
if [ $? -ne 0 ]; then
echo "*** Failed to delete security group $SECURITY_GROUP."
exit 1
fi
echo "Security Group $SECURITY_GROUP is deleted successfully."
openstack floating ip delete $FLOATING_IP_ADDRESS
if [ $? -ne 0 ]; then
echo "*** Failed to delete floating ip $FLOATING_IP_ADDRESS."
exit 1
fi
echo "Floating IP $FLOATING_IP is released successfully."
echo "Kubernetes ephemeral cluster on vm $CAPI_VM is deleted successfully."

View File

@ -0,0 +1,32 @@
Openstack Ephemeral Configuration File Definition
-----------------------------------------------------
The Openstack Bootstrap container creates an Ephemeral K8S cluster on the Openstack.
The container requires clouds.yaml credentials and other information about the cluster to deploy.
It requires a YAML configuration file with the format provided below.
<Openstack Config Definition>
apiVersion: v1
kind: OpenstackConfig
metadata:
name: <metadata-name>
credentials:
credential: <Clouds.yaml file of devstack>
cloudName: <openstack cloud name i.e. devstack>
spec:
cluster:
machineSize: <Openstack VM flavor, e.g. ds2G>
kubeconfig: <Kubeconfig filename, Default is 'kubeconfig'>
securityGroup:<Security Group that'll be attached to the VM>
</Openstack Config Definition>
The expected location for the Openstack bootstrap configuration file is dictated by the "volume" mount
specified in the Airship config file (bootstrapInfo.ephemeral.container.volume).
For example, $HOME/.airship folder and shown in the snippet below:
<Snippet>
apiVersion: airshipit.org/v1alpha1
bootstrapInfo:
ephemeral:
container:
volume: /home/stack/.airship:/kube
</Snippet>

View File

@ -0,0 +1,55 @@
#!/bin/sh
DEBIAN_FRONTEND=noninteractive apt-get remove -y resolvconf
sed -i 's/domain-name-servers, domain-search, //' /etc/dhcp/dhclient.conf
service networking restart
sed -i '/nameserver/d' /etc/resolv.conf
export NAMESERVER=${NAMESERVER:-8.8.8.8}
export NAMESERVER_OTHER=${NAMESERVER_OTHER:-8.8.4.4}
echo 'nameserver '"$NAMESERVER" >> /etc/resolv.conf
echo 'nameserver '"$NAMESERVER_OTHER" >> /etc/resolv.conf
echo "nameserver is set"
apt-get update
apt-get upgrade -y
apt-get install -y apt-transport-https ca-certificates curl \
software-properties-common
apt-get install -y docker.io
bash -c 'cat << EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF'
export APT_KEY_GPG_URL=${APT_KEY_GPG_URL:-https://packages.cloud.google.com/apt/doc/apt-key.gpg}
export K8S_IO_DEB_URL=${K8S_IO_DEB_URL:-http://apt.kubernetes.io/}
curl -s "$APT_KEY_GPG_URL" | sudo apt-key add -
bash -c 'cat << EOF > /etc/apt/sources.list.d/kubernetes.list
deb $K8S_IO_DEB_URL kubernetes-xenial main
EOF'
export K8S_VERSION=${K8S_VERSION:-1.19.0-00}
apt update
apt install -y kubelet="$K8S_VERSION" kubeadm="$K8S_VERSION" kubectl="$K8S_VERSION"
export CONTROL_PLANE_IP=${CONTROL_PLANE_IP:-172.24.4.199}
kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-cert-extra-sans="$CONTROL_PLANE_IP" \
--control-plane-endpoint="$CONTROL_PLANE_IP"
mkdir -p /home/ubuntu/.kube
cp -i /etc/kubernetes/admin.conf /home/ubuntu/.kube/config
chown ubuntu:ubuntu /home/ubuntu/.kube/config
export CALICO_URL=${CALICO_URL:-https://docs.projectcalico.org/v3.15/manifests/calico.yaml}
export KUBECONFIG=/etc/kubernetes/admin.conf && \
kubectl apply -f "$CALICO_URL"

View File

@ -0,0 +1,28 @@
# Copyright 2018 AT&T Intellectual Property. All other rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
- hosts: primary
vars_files:
- vars/version.yaml
tasks:
- name: install go language
shell: |
sudo -E curl -sO "{{url}}"/go/"{{golang_version}}".tar.gz
sudo tar -C /usr/local -xzf "{{golang_version}}".tar.gz
rm "{{golang_version}}".tar.gz
cat >> ~/.profile << EOF
export PATH=$PATH:/usr/local/go/bin
EOF
become: yes
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'

View File

@ -0,0 +1,3 @@
---
golang_version: go1.14.1.linux-amd64
url: https://dl.google.com