Skip to content

Commit 476068b

Browse files
odracciwayne.morris
authored and
wayne.morris
committed
AIRFLOW-2952 Fix Kubernetes CI (apache#3922)
The current dockerised CI pipeline doesn't run minikube and the Kubernetes integration tests. This starts a Kubernetes cluster using minikube and runs k8s integration tests using docker-compose.
1 parent c2719b9 commit 476068b

17 files changed

+175
-47
lines changed

.travis.yml

+20-12
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,37 @@ env:
2626
- TRAVIS_CACHE=$HOME/.travis_cache/
2727
matrix:
2828
- TOX_ENV=flake8
29-
- TOX_ENV=py27-backend_mysql
30-
- TOX_ENV=py27-backend_sqlite
31-
- TOX_ENV=py27-backend_postgres
32-
- TOX_ENV=py35-backend_mysql PYTHON_VERSION=3
33-
- TOX_ENV=py35-backend_sqlite PYTHON_VERSION=3
34-
- TOX_ENV=py35-backend_postgres PYTHON_VERSION=3
35-
- TOX_ENV=py27-backend_postgres KUBERNETES_VERSION=v1.9.0
36-
- TOX_ENV=py35-backend_postgres KUBERNETES_VERSION=v1.10.0 PYTHON_VERSION=3
29+
- TOX_ENV=py27-backend_mysql-env_docker
30+
- TOX_ENV=py27-backend_sqlite-env_docker
31+
- TOX_ENV=py27-backend_postgres-env_docker
32+
- TOX_ENV=py35-backend_mysql-env_docker PYTHON_VERSION=3
33+
- TOX_ENV=py35-backend_sqlite-env_docker PYTHON_VERSION=3
34+
- TOX_ENV=py35-backend_postgres-env_docker PYTHON_VERSION=3
35+
- TOX_ENV=py27-backend_postgres-env_kubernetes KUBERNETES_VERSION=v1.9.0
36+
- TOX_ENV=py35-backend_postgres-env_kubernetes KUBERNETES_VERSION=v1.10.0 PYTHON_VERSION=3
37+
3738
cache:
3839
directories:
3940
- $HOME/.wheelhouse/
4041
- $HOME/.cache/pip
4142
- $HOME/.travis_cache/
4243
before_install:
43-
- sudo ls -lh $HOME/.cache/pip/
44-
- sudo rm -rf $HOME/.cache/pip/* $HOME/.wheelhouse/*
45-
- sudo chown -R travis:travis $HOME/.cache/pip
44+
# Required for K8s v1.10.x. See
45+
# https://github.com/kubernetes/kubernetes/issues/61058#issuecomment-372764783
46+
- if [ ! -z "$KUBERNETES_VERSION" ]; then sudo mount --make-shared / && sudo service docker restart; fi
4647
install:
4748
# Use recent docker-compose version
4849
- sudo rm /usr/local/bin/docker-compose
4950
- curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
5051
- chmod +x docker-compose
5152
- sudo mv docker-compose /usr/local/bin
5253
- pip install --upgrade pip
54+
- if [ ! -z "$KUBERNETES_VERSION" ]; then ./scripts/ci/kubernetes/setup_kubernetes.sh; fi
5355
script:
54-
- docker-compose --log-level ERROR -f scripts/ci/docker-compose.yml run airflow-testing /app/scripts/ci/run-ci.sh
56+
- if [ -z "$KUBERNETES_VERSION" ]; then docker-compose --log-level ERROR -f scripts/ci/docker-compose.yml run airflow-testing /app/scripts/ci/run-ci.sh; fi
57+
- if [ ! -z "$KUBERNETES_VERSION" ]; then
58+
./scripts/ci/kubernetes/kube/deploy.sh &&
59+
MINIKUBE_IP=$(minikube ip) docker-compose --log-level ERROR -f scripts/ci/docker-compose.yml -f scripts/ci/docker-compose-kubernetes.yml run airflow-testing /app/scripts/ci/run-ci.sh;
60+
fi
61+
before_cache:
62+
- sudo chown -R travis:travis $HOME/.cache/pip $HOME/.wheelhouse/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Licensed to the Apache Software Foundation (ASF) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The ASF licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Licensed to the Apache Software Foundation (ASF) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The ASF licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
from __future__ import print_function
20+
import airflow
21+
from airflow.operators.python_operator import PythonOperator
22+
from airflow.models import DAG
23+
24+
args = {
25+
'owner': 'airflow',
26+
'start_date': airflow.utils.dates.days_ago(2)
27+
}
28+
29+
dag = DAG(
30+
dag_id='example_kubernetes_annotation', default_args=args,
31+
schedule_interval=None
32+
)
33+
34+
35+
def print_stuff():
36+
print("annotated!")
37+
38+
39+
# You can use annotations on your kubernetes pods!
40+
start_task = PythonOperator(
41+
task_id="start_task", python_callable=print_stuff, dag=dag,
42+
executor_config={
43+
"KubernetesExecutor": {
44+
"annotations": {"test": "annotation"}
45+
}
46+
}
47+
)

scripts/ci/5-run-tests.sh

+9-5
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,11 @@ which airflow > /dev/null || python setup.py develop
5858
# (which contains /usr/local/bin)
5959
sudo ln -sf "${VIRTUAL_ENV}/bin/airflow" /usr/local/bin/
6060

61-
echo "Initializing the DB"
62-
yes | airflow initdb
63-
yes | airflow resetdb
61+
if [ -z "$KUBERNETES_VERSION" ]; then
62+
echo "Initializing the DB"
63+
yes | airflow initdb
64+
yes | airflow resetdb
65+
fi
6466

6567
if [ -z "$nose_args" ]; then
6668
nose_args="--with-coverage \
@@ -75,8 +77,10 @@ if [ -z "$nose_args" ]; then
7577
--logging-level=DEBUG"
7678
fi
7779

78-
# kdc init happens in setup_kdc.sh
79-
kinit -kt ${KRB5_KTNAME} airflow
80+
if [ -z "$KUBERNETES_VERSION" ]; then
81+
# kdc init happens in setup_kdc.sh
82+
kinit -kt ${KRB5_KTNAME} airflow
83+
fi
8084

8185
# For impersonation tests running on SQLite on Travis, make the database world readable so other
8286
# users can update it
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
version: "2.2"
18+
services:
19+
airflow-testing:
20+
network_mode: host
21+
environment:
22+
- KUBERNETES_VERSION
23+
- MINIKUBE_IP
24+
volumes:
25+
- /usr/local/bin/kubectl:/usr/local/bin/kubectl
26+
- /usr/local/bin/minikube:/usr/local/bin/minikube
27+
- ~/.kube:/home/airflow/.kube
28+
- ~/.minikube:/home/airflow/.minikube

scripts/ci/kubernetes/docker/airflow-test-env-init.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
# under the License.
1919

2020
cd /usr/local/lib/python2.7/dist-packages/airflow && \
21-
cp -R example_dags/* /root/airflow/dags/ && \
21+
cp -R example_dags_kubernetes/* /root/airflow/dags/ && \
2222
airflow initdb && \
2323
alembic upgrade heads && \
2424
(airflow create_user -u airflow -l airflow -f jon -e airflow@apache.org -r Admin -p airflow || true) && \

scripts/ci/kubernetes/docker/build.sh

+7-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ TAG=${2:-latest}
2222
DIRNAME=$(cd "$(dirname "$0")"; pwd)
2323
AIRFLOW_ROOT="$DIRNAME/../../../.."
2424

25-
ENVCONFIG=$(minikube docker-env)
26-
if [ $? -eq 0 ]; then
27-
eval $ENVCONFIG
25+
set -e
26+
27+
if [ "${VM_DRIVER:-none}" != "none" ]; then
28+
ENVCONFIG=$(minikube docker-env)
29+
if [ $? -eq 0 ]; then
30+
eval $ENVCONFIG
31+
fi
2832
fi
2933

3034
echo "Airflow directory $AIRFLOW_ROOT"

scripts/ci/kubernetes/kube/airflow.yaml

-1
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,3 @@ spec:
151151
nodePort: 30809
152152
selector:
153153
name: airflow
154-

scripts/ci/kubernetes/kube/configmaps.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ data:
2727
logging_level = INFO
2828
executor = KubernetesExecutor
2929
parallelism = 32
30-
load_examples = True
30+
load_examples = False
3131
plugins_folder = /root/airflow/plugins
3232
sql_alchemy_conn = $SQL_ALCHEMY_CONN
3333

scripts/ci/kubernetes/kube/deploy.sh

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
# specific language governing permissions and limitations *
1818
# under the License. *
1919

20+
set -x
21+
2022
IMAGE=${1:-airflow/ci}
2123
TAG=${2:-latest}
2224
DIRNAME=$(cd "$(dirname "$0")"; pwd)

scripts/ci/kubernetes/minikube/start_minikube.sh

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919

2020
#!/usr/bin/env bash
2121

22+
set -x
2223

2324
_MY_SCRIPT="${BASH_SOURCE[0]}"
2425
_MY_DIR=$(cd "$(dirname "$_MY_SCRIPT")" && pwd)
2526
# Avoids 1.7.x because of https://github.com/kubernetes/minikube/issues/2240
2627
_KUBERNETES_VERSION="${KUBERNETES_VERSION}"
27-
_MINIKUBE_VERSION="${MINIKUBE_VERSION:-v0.26.0}"
28+
_MINIKUBE_VERSION="${MINIKUBE_VERSION:-v0.28.2}"
2829

2930
echo "setting up kubernetes ${_KUBERNETES_VERSION}, using minikube ${_MINIKUBE_VERSION}"
3031

@@ -116,7 +117,7 @@ echo Showing kube-system pods
116117
kubectl get -n kube-system pods
117118

118119
(k8s_single_pod_ready -n kube-system -l component=kube-addon-manager) ||
119-
(_ADDON=$(kubectl get pod -n kube-system -l component=kube-addon-manager
120+
(_ADDON=$(kubectl get pod -n kube-system -l component=kube-addon-manager \
120121
--no-headers -o name| cut -d/ -f2);
121122
echo Addon-manager describe:;
122123
kubectl describe pod -n kube-system $_ADDON;

scripts/ci/kubernetes/setup_kubernetes.sh

-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,5 @@ DIRNAME=$(cd "$(dirname "$0")"; pwd)
2525

2626
$DIRNAME/minikube/start_minikube.sh
2727
$DIRNAME/docker/build.sh
28-
$DIRNAME/kube/deploy.sh
2928

3029
echo "Airflow environment on kubernetes is good to go!"

scripts/ci/run-ci.sh

+8-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ DIRNAME=$(cd "$(dirname "$0")"; pwd)
2424
AIRFLOW_ROOT="$DIRNAME/../.."
2525

2626
# Fix file permissions
27-
sudo chown -R airflow.airflow . $HOME/.wheelhouse/ $HOME/.cache/pip
27+
sudo chown -R airflow.airflow . $HOME/.cache $HOME/.wheelhouse/ $HOME/.cache/pip $HOME/.kube $HOME/.minikube
2828

2929
if [[ $PYTHON_VERSION == '3' ]]; then
3030
PIP=pip3
@@ -41,7 +41,13 @@ if [ -z "$KUBERNETES_VERSION" ];
4141
then
4242
tox -e $TOX_ENV
4343
else
44-
KUBERNETES_VERSION=${KUBERNETES_VERSION} $DIRNAME/kubernetes/setup_kubernetes.sh && \
44+
# This script runs inside a container, the path of the kubernetes certificate
45+
# is /home/travis/.minikube/client.crt but the user in the container is `airflow`
46+
if [ ! -d /home/travis ]; then
47+
sudo mkdir -p /home/travis
48+
fi
49+
sudo ln -s /home/airflow/.minikube /home/travis/.minikube
50+
4551
tox -e $TOX_ENV -- tests.contrib.minikube \
4652
--with-coverage \
4753
--cover-erase \

tests/contrib/minikube/test_kubernetes_executor.py

+16-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# under the License.
1717

1818

19+
import os
1920
import unittest
2021
from subprocess import check_call, check_output
2122
import requests.exceptions
@@ -25,18 +26,25 @@
2526
import re
2627

2728
try:
28-
check_call(["kubectl", "get", "pods"])
29+
check_call(["/usr/local/bin/kubectl", "get", "pods"])
2930
except Exception as e:
30-
raise unittest.SkipTest(
31-
"Kubernetes integration tests require a minikube cluster;"
32-
"Skipping tests {}".format(e)
33-
)
31+
if os.environ.get('KUBERNETES_VERSION'):
32+
raise e
33+
else:
34+
raise unittest.SkipTest(
35+
"Kubernetes integration tests require a minikube cluster;"
36+
"Skipping tests {}".format(e)
37+
)
3438

3539

3640
def get_minikube_host():
37-
host_ip = check_output(['minikube', 'ip'])
38-
if six.PY3:
39-
host_ip = host_ip.decode('UTF-8')
41+
if "MINIKUBE_IP" in os.environ:
42+
host_ip = os.environ['MINIKUBE_IP']
43+
else:
44+
host_ip = check_output(['/usr/local/bin/minikube', 'ip'])
45+
if six.PY3:
46+
host_ip = host_ip.decode('UTF-8')
47+
4048
host = '{}:30809'.format(host_ip.strip())
4149
return host
4250

tests/contrib/minikube/test_kubernetes_pod_operator.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@
2929
from airflow.contrib.kubernetes.volume import Volume
3030

3131
try:
32-
check_call(["kubectl", "get", "pods"])
32+
check_call(["/usr/local/bin/kubectl", "get", "pods"])
3333
except Exception as e:
34-
raise unittest.SkipTest(
35-
"Kubernetes integration tests require a minikube cluster;"
36-
"Skipping tests {}".format(e)
37-
)
34+
if os.environ.get('KUBERNETES_VERSION'):
35+
raise e
36+
else:
37+
raise unittest.SkipTest(
38+
"Kubernetes integration tests require a minikube cluster;"
39+
"Skipping tests {}".format(e)
40+
)
3841

3942

4043
class KubernetesPodOperatorTest(unittest.TestCase):

tests/core.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ def reset(dag_id=TEST_DAG_ID):
9797

9898

9999
configuration.conf.load_test_config()
100-
reset()
100+
if os.environ.get('KUBERNETES_VERSION') is None:
101+
reset()
101102

102103

103104
class OperatorSubclass(BaseOperator):

tox.ini

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# under the License.
1818

1919
[tox]
20-
envlist = flake8,{py27,py35}-backend_{mysql,sqlite,postgres}
20+
envlist = flake8,{py27,py35}-backend_{mysql,sqlite,postgres}-env_{docker,kubernetes}
2121
skipsdist = True
2222

2323
[global]
@@ -57,10 +57,10 @@ passenv = *
5757
commands =
5858
pip wheel --progress-bar off -w {homedir}/.wheelhouse -f {homedir}/.wheelhouse -e .[devel_ci]
5959
pip install --progress-bar off --find-links={homedir}/.wheelhouse --no-index -e .[devel_ci]
60-
{toxinidir}/scripts/ci/1-setup-env.sh
61-
{toxinidir}/scripts/ci/2-setup-kdc.sh
62-
{toxinidir}/scripts/ci/3-setup-databases.sh
63-
{toxinidir}/scripts/ci/4-load-data.sh
60+
env_docker: {toxinidir}/scripts/ci/1-setup-env.sh
61+
env_docker: {toxinidir}/scripts/ci/2-setup-kdc.sh
62+
env_docker: {toxinidir}/scripts/ci/3-setup-databases.sh
63+
env_docker: {toxinidir}/scripts/ci/4-load-data.sh
6464
{toxinidir}/scripts/ci/5-run-tests.sh []
6565
{toxinidir}/scripts/ci/6-check-license.sh
6666
codecov -e TOXENV

0 commit comments

Comments
 (0)