k8sのバージョンが原因でSparkのexecutorコンテナがひたすらエラーになり続けた話

## 0. TL;DR
* 発生タイミング：Spark2.4.0を元に作成したSparkコンテナをKubernetes上で実行
* 表面的問題：SparkのExecutorコンテナがひたすら消滅と生成を繰り返し処理が終わらない
* 原因と対策：Kubernetesのバージョンを1.10.3から1.11.8に引き上げたら解消

## 1. 問題詳細
### 1.1. 環境とか
* Azure Kubernetes Service(AKS)
    * Kubernetesのバージョン：1.10.3
* Apache Spark2.4.0
    * [公式サイト](https://archive.apache.org/dist/spark/spark-2.4.0/spark-2.4.0-bin-hadoop2.7.tgz)よりダウンロードしビルドしたものを利用
* 実行プログラム(Spark付属のサンプルプログラム)
    * class：org.apache.spark.examples.SparkPi
    * jar：/spark/examples/jars/spark-examples_2.11-2.4.0.jar

### 1.2. 経緯
#### 1.2.1. ひたすらexecutorが消滅・生成を繰り返す
spark-submitでAKS上でSpark処理を行ったところ処理がいつまでたっても終わらない。
```kubectl get pods```で確認してみると、5秒おき毎にexecutorがerrorとなり新しいexecutorが生成されている……
Sparkが2.3.x系統のときにはこんな問題は発生しなかったのに……

#### 1.2.2. executorのエラー内容確認
Spark on Kubernetesでは処理が終了したexecutorのpodは削除されてしまうため、削除される前に```kubectl logs [pod名]```で出力されているスタックトレースを確認。
一見するとdriverとexecutorが相互認識できなくなったかのようなエラー内容であるが、**実際は違う(後述)**。
ホストの設定とかいろいろやってみたが解決しなかった。

```
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1713)
	at org.apache.spark.deploy.SparkHadoopUtil.runAsSparkUser(SparkHadoopUtil.scala:64)
	at org.apache.spark.executor.CoarseGrainedExecutorBackend$.run(CoarseGrainedExecutorBackend.scala:188)
	at org.apache.spark.executor.CoarseGrainedExecutorBackend$.main(CoarseGrainedExecutorBackend.scala:281)
	at org.apache.spark.executor.CoarseGrainedExecutorBackend.main(CoarseGrainedExecutorBackend.scala)
Caused by: org.apache.spark.SparkException: Exception thrown in awaitResult: 
	at org.apache.spark.util.ThreadUtils$.awaitResult(ThreadUtils.scala:226)
	at org.apache.spark.rpc.RpcTimeout.awaitResult(RpcTimeout.scala:75)
	at org.apache.spark.rpc.RpcEnv.setupEndpointRefByURI(RpcEnv.scala:101)
	at org.apache.spark.executor.CoarseGrainedExecutorBackend$$anonfun$run$1.apply$mcV$sp(CoarseGrainedExecutorBackend.scala:201)
	at org.apache.spark.deploy.SparkHadoopUtil$$anon$2.run(SparkHadoopUtil.scala:65)
	at org.apache.spark.deploy.SparkHadoopUtil$$anon$2.run(SparkHadoopUtil.scala:64)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1698)
	... 4 more
Caused by: java.io.IOException: Failed to connect to spark-pi-1551623978810-driver-svc.default.svc:7078
	at org.apache.spark.network.client.TransportClientFactory.createClient(TransportClientFactory.java:245)
	at org.apache.spark.network.client.TransportClientFactory.createClient(TransportClientFactory.java:187)
	at org.apache.spark.rpc.netty.NettyRpcEnv.createClient(NettyRpcEnv.scala:198)
	at org.apache.spark.rpc.netty.Outbox$$anon$1.call(Outbox.scala:194)
	at org.apache.spark.rpc.netty.Outbox$$anon$1.call(Outbox.scala:190)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.UnknownHostException: spark-pi-1551623978810-driver-svc.default.svc
	at java.net.InetAddress.getAllByName0(InetAddress.java:1281)
	at java.net.InetAddress.getAllByName(InetAddress.java:1193)
	at java.net.InetAddress.getAllByName(InetAddress.java:1127)
	at java.net.InetAddress.getByName(InetAddress.java:1077)
	at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:146)
	at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:143)
	at java.security.AccessController.doPrivileged(Native Method)
	at io.netty.util.internal.SocketUtils.addressByName(SocketUtils.java:143)
	at io.netty.resolver.DefaultNameResolver.doResolve(DefaultNameResolver.java:43)
	at io.netty.resolver.SimpleNameResolver.resolve(SimpleNameResolver.java:63)
	at io.netty.resolver.SimpleNameResolver.resolve(SimpleNameResolver.java:55)
	at io.netty.resolver.InetSocketAddressResolver.doResolve(InetSocketAddressResolver.java:57)
	at io.netty.resolver.InetSocketAddressResolver.doResolve(InetSocketAddressResolver.java:32)
	at io.netty.resolver.AbstractAddressResolver.resolve(AbstractAddressResolver.java:108)
	at io.netty.bootstrap.Bootstrap.doResolveAndConnect0(Bootstrap.java:208)
	at io.netty.bootstrap.Bootstrap.access$000(Bootstrap.java:49)
	at io.netty.bootstrap.Bootstrap$1.operationComplete(Bootstrap.java:188)
	at io.netty.bootstrap.Bootstrap$1.operationComplete(Bootstrap.java:174)
	at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:507)
	at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:481)
	at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:420)
	at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:104)
	at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:82)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.safeSetSuccess(AbstractChannel.java:978)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:512)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:423)
	at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:482)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:403)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:463)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
	at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
```

#### 1.2.3. Docker for Mac上のKubernetes環境では動作
別のKubernetes環境でも再現するかを確かめるため、ローカルのDocker for Mac上のKubernetesで同じコンテナを動かしてみたところ、きちんと上記エラーは発生せず、プログラムの最終ゴールであるdriverコンテナのterminateされるところまで見届けることができた。
ここでKuberntesのバージョンの相違の可能性が頭に浮かび、下記コマンドを実行したところ確かにバージョンが違う。

```
kubectl version

# Docker for Macの方 : v1.11.2
# Azure Kubernetes Serviceの方 : v1.10.3
```

### 1.3 解決
AKSのKubernetesのバージョンを引き上げたら解決。
Azureポータル画面からAKSのKubernetsバージョンを引き上げることができるので1.11系列である1.11.8まで引き上げた。
この環境でSparkを実行したところ、エラーなくdriverコンテナのterminateまで完了した。

## 2. 反省点
**当たり前のことではあるが、バージョンはちゃんと確認しないといけない。**
とはいえサンプルプログラムすら動かなくなるとは思わなかった
(一応公式サイトでは1.6以上で動くって書いてある)。