Developing for Kubernetes with minikube
This guide is meant to serve as a cross-plaform resource for setting up a local Kubernetes development environment. In this guide, we’ll be using minikube as it is the accepted standard.
Getting Started with minikube
We’ll extract and expound on the official documentation from the Kubernetes project, Running Kubernetes Locally with minikube.
Installing kubectl
The official documentation provides several options, but the result is that you can do one of three things:
-
Download as a part of the Google Cloud SDK from Google Cloud Platform’s Cloud SDK page. Once you have
gcloud
installed, you can installkubectl
:sudo gcloud components install kubectl
If you’ve already installed
kubectl
via this method, ensure it is updated:sudo gcloud components update
-
Install with cURL or with the appropriate package management system for each OS:
Installing minikube
See the Kubernetes documentation where they suggest directly installing from the releases on GitHub.
Choosing a VM driver
For the purposes of cross-platform compatibility in this guide, we’ll stick with VirtualBox, however there are drivers for VMware Fusion, HyperV, KVM, and Xhyve.
Starting / Stopping minikube
minikube resource requests must be set higher than the default for developing
the GitLab chart. The key configuration items can be found with
minikube start --help
. A selection is provided below, for what we may want to
change according to the pieces being tested, and the requirements as listed:
-
--cpus int
: Number of CPUs allocated to the minikube VM (default2
). The absolute minimum necessary CPU is3
. Deploying the complete chart requires4
. -
--memory int
: Amount of RAM allocated to the minikube VM (default2048
). The absolute same minimum is6144
(6 GB). Recommendation is10240
(10 GB). -
--disk-size string
: Disk size allocated to the minikube VM (format:<number>[<unit>]
, where unit =b
,k
,m
org
) (default20g
). See the GitLab storage and database requirements.This is created in your home directory under~/.minikube/machines/minikube/
. -
--kubernetes-version string
: The Kubernetes version that the minikube VM will use (e.g.,v1.2.3
). -
--registry-mirror stringSlice
: Registry mirrors to pass to the Docker daemon.
start
command, requires to first delete
the existing instance with minikube delete
, or manually you can alter the
properties with VirtualBox Manager.Once you have all the tools installed and configured, starting at stopping minikube can be done with:
minikube start --cpus 4 --memory 10240
This command should output something similar to:
Starting local Kubernetes v1.7.0 cluster...
Starting VM...
Downloading Minikube ISO
97.80 MB / 97.80 MB [==============================================] 100.00% 0s
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Starting cluster components...
Connecting to cluster...
Setting up kubeconfig...
Kubectl is now configured to use the cluster.
[helm.gitlab.io]$ minikube ip
192.168.99.100
[helm.gitlab.io]$ minikube stop
Stopping local Kubernetes cluster...
Machine stopped.
Take note of the result from running the minikube ip
command. If the output is not 192.168.99.100
, the output IP will be needed later.
Using minikube
minikube can be used directly as a Kubernetes installation, and treated as a single node cluster. There are some behaviors that are slightly different between minikube and full-fledged Kubernetes clusters, such as Google Container Engine (GKE).
Different:
- Persistent Volumes:
hostPath
only.
Unavailable:
- Load Balancers (requires cloud provider).
- Advanced Scheduling Policies (requires multiple nodes).
Gotcha: Persistent Volumes
minikube supports PersistentVolumes
of the hostPath
type, which are mapped to directories inside the VM. As minikube
boots into a tmpfs
, most directories will not persist across reboots via minikube stop
.
Further details and listings of directories that do persist, can be found in the minikube getting started guide.
Enable Add-ons
minikube handles some features apart from the base configuration. For the
development of this project, we’ll need access to Ingress
:
minikube addons enable ingress
Connecting to the dashboard
You can find the URL for the dashboard by calling:
minikube dashboard --url
Deploying the chart
When deploying this chart into minikube, some chart resources need to be reduced or disabled.
It is not possible to use the nginx-ingress
chart to provide ports 22
, 80
,
443
. It’s best to disable it and set the Ingress class by setting
nginx-ingress.enabled=false,global.ingress.class="nginx"
.
The certmanager
chart can not be used with minikube. You must disable this by
setting certmanager.install=false,global.ingress.configureCertmanager=false
.
As a result, if you don’t provide your own SSL certificates, self-signed
certificates will be generated. The gitlab-runner
chart will accept the self-signed
certificates via gitlab-runner.certsSecretName
. Assuming your release name is gitlab
,
the certificate name will be gitlab-wildcard-tls-chain
.
The gitlab-shell
chart can be used with minikube, but requires mapping to a port other
than 22 as it used by minikube already. You can configure gitlab.gitlab-shell.service.type=NodePort
and gitlab.gitlab-shell.service.nodePort=<high-numbered port>
, which will allow cloning a repository
via the specified port. To ensure this port is reflected in the clone link in the UI, configure
global.shell.port=<high-numbered port>
.
In the following sections, we’ll show how to install these charts from your local Git clone. Be sure that you have checked out the desired branch or tag, and are at the base folder of that checkout.
Clone GitLab chart repo
git clone https://gitlab.com/gitlab-org/charts/gitlab.git
cd gitlab
Deploying GitLab with recommended settings
When using the recommended 4 CPU and 10 GB of RAM, use
values-minikube.yaml
as a base.
helm dependency update
helm upgrade --install gitlab . \
--timeout 600s \
-f https://gitlab.com/gitlab-org/charts/gitlab/raw/master/examples/values-minikube.yaml
Deploying GitLab with minimal settings
If using absolute minimum resources, 3 CPU and 6GB of RAM, you must reduce all replicas
and disable unneeded services. See values-minikube-minimum.yaml
as a reasonable base.
helm dependency update
helm upgrade --install gitlab . \
--timeout 600s \
-f https://gitlab.com/gitlab-org/charts/gitlab/raw/master/examples/values-minikube-minimum.yaml
If the output of minikube ip
was not 192.168.99.100
, add these arguments to override the IP endpoints in the example configuration files:
--set global.hosts.domain=$(minikube ip).nip.io \
--set global.hosts.externalIP=$(minikube ip)
Handling DNS
The example configurations provided, configure the domain as 192.168.99.100.nip.io
in an attempt to reduce the overhead of handling alterations to host files, or
other domain name resolution services. However, this relies on the network
reachability of nip.io.
If this is not available to you, then you may need to make alterations to your
/etc/hosts
file, or provide another means of DNS resolution.
Example /etc/hosts
file addition:
192.168.99.100 gitlab.some.domain registry.some.domain minio.some.domain
Incorporating Self-Signed CA
Once the chart is deployed, if using self-signed certificates, the user will be
given the notice on how to fetch the CA certificate that was generated. This
certificate can be added to the system store, so that all browsers, Docker daemon,
and git
command recognize the deployed certificates as trusted. The method
depends on your operating system.
BounCA has a good tutorial, covering most operating systems.
Logging in
You can access the GitLab instance by visiting the domain specified, https://gitlab.192.168.99.100.nip.io
is used in these examples. If you manually created the secret for initial root password, you can use that to sign in as root user. If not, GitLab automatically created a random password for the root user. This can be extracted by the following command (replace <name>
by name of the release - which is gitlab
if you used the command above).
kubectl get secret <name>-gitlab-initial-root-password -ojsonpath='{.data.password}' | base64 --decode ; echo