AWSで作るクラウドネイティブアプリケーションの基本とDevOps
2019.9.20




※当スライドは 「reveal.js」 を使って、GitHub Pages上に作成

AWSクラウドでよく利用される基本的なサービスの構築方法や、SpringBootをベースとしてクラウド特有の特徴を活用したアプリケーションを実装する際の基本事項をまとめた連載記事










クラウドネイティブECSコンテナ編の環境でMSAアプリケーションを構築




GitHubフローをベースにしたブランチ戦略


Backendコンテナイメージの作成・プッシュ

ステージング環境へのBackendコンテナデプロイ

WebアプリケーションでのE2Eテスト・コンテナイメージ作成

Webアプリケーションのコンテナイメージのプッシュ

ステージング環境へのWebアプリケーションのコンテナデプロイ

ステージング環境でのその他テスト実行・管理者の承認プロセス

Backend・Webアプリケーションのコンテナイメージの並行プッシュ

プロダクション環境へのBackend・Webアプリケーションのコンテナ並行デプロイ


クラウドネイティブアプリケーションのポイント

例外ハンドリングが大変な例(動画をアップしてサムネイルを作る処理)


A. 下記の案もありました。

が、下記の理由によりやめました。

結局、この形にしました。しかし、この構成が唯一の正解というわけではありません。

ただし、以下のようなメリットを得ることはできます。


@Configuration
@EnableRdsInstance(
dbInstanceIdentifier = "${rds.identifier}",
password ="${rds.password}",
readReplicaSupport = false)
public class RdsConfig {
}
rds:
identifier: ${RDS_IDENTIFIER}
password: ${RDS_PASSWORD}

[ポイント]各データベースに適したユースケースやデータ特性
NoSQLは色々種類や特徴があるが、ユースケースやデータ特性に適したものを選択すべき。
| タイプ | ユースケース/データ特性 | 使いどころ |
|---|---|---|
| CA型 | 複雑な条件 | 集合関数や射影/結合/副問い合わせ等 |
| 厳密なトランザクション/整合性 | 多額の決済データ、人命に関わるようなデータ | |
| 高負荷アップデート | 正規化を前提としたデータモデル | |
| CP型 | キャッシュ | 一部が利用できなくても大きな問題はない |
| 高速バッチ処理 | シャーディングによる高速処理 | |
| AP型 | スケーラブルアプリケーション | ノードの追加を動的に行いたい |
| マルチリージョン | グローバルなデータセンタ間のデータ共有 | |
| 大量の書き込み | 単一障害点がないため、IoTセンサーデータなど大量書き込み |


[補足]マルチAZでのフェイルオーバー
| ElastiCache Multi-AZ | Redis Sentinel | |
|---|---|---|
| Spring Cloud AWS Support | ○ | × |
| Spring Data Redis Support | × | ○ |
| ダウンタイム | 数分※ | 即時 |
| AWSマネージド | ○ | × |
| エンドポイント変更 | なし | あり |

[ポイント]認証キーの取り扱い方 - よくない例 - ![]()
@Configuration
public class S3Config {
@Value("${cloud.aws.credentials.accessKey}")
private String accessKey;
@Value("${cloud.aws.credentials.secretKey}")
private String secretKey;
@Value("${cloud.aws.region.static}")
private String region;
@Bean
public BasicAWSCredentials basicAWSCredentials() {
return new BasicAWSCredentials(accessKey, secretKey);
}
@Bean
public AmazonS3 amazonS3Client(AWSCredentials awsCredentials) {
return AmazonS3ClientBuilder.standard().withRegion(Regions.fromName(region)).build();
}
}
cloud.aws.credentials.accessKey=XXXXXXXXXXXXXX
cloud.aws.credentials.secretKey=YYYYYYYYYYYYYY
cloud.aws.region.static=ap-northeast-1
cloud.aws.region.auto=false
[ポイント]認証キーの取り扱い方 - ダメじゃないけどイマイチな例 - ![]()
@Configuration
public class S3Config {
@Value("${cloud.aws.credentials.accessKey}")
private String accessKey;
@Value("${cloud.aws.credentials.secretKey}")
private String secretKey;
@Value("${cloud.aws.region.static}")
private String region;
@Bean
public BasicAWSCredentials basicAWSCredentials() {
return new BasicAWSCredentials(accessKey, secretKey);
}
@Bean
public AmazonS3 amazonS3Client(AWSCredentials awsCredentials) {
return AmazonS3ClientBuilder.standard().withRegion(Regions.fromName(region)).build();
}
}
cloud:
aws:
credentials:
accessKey: ${AWS_ACCESS_KEY_ID}
secretKey: ${AWS_SECRET_ACCESS_KEY}
[ポイント]認証キーの取り扱い方 - よい例 - ![]()
@Configuration
public class S3Config {
@Bean
public AmazonS3 amazonS3(){
return AmazonS3ClientBuilder.standard().build();
}
}
クラウド特有の実装:STSを使ったS3ダイレクトアップロード・ダウンロード


[ポイント]SpringCloudAWSを使ったSQS Producer-Consumerアプリケーション
Producer設定クラス
@Configuration
public class SqsConfig {
@Value("${queue.endpoint}")
private String queueEndpoint;
@Value("${cloud.aws.region.static}")
private String region;
@Autowired
AmazonSQSAsync amazonSQSAsync;
@Bean
public AwsClientBuilder.EndpointConfiguration endpointConfiguration(){
return new AwsClientBuilder.EndpointConfiguration(queueEndpoint, region);
}
@Bean
public QueueMessagingTemplate queueMessagingTemplate(){
return new QueueMessagingTemplate(amazonSQSAsync);
}
}
[ポイント]SpringCloudAWSを使ったSQS Producer-Consumerアプリケーション
ProducerRepository
import org.springframework.cloud.aws.messaging.core.QueueMessagingTemplate;
@Component
public class SampleRepositoryImpl implements SampleRepository{
@Autowired
QueueMessagingTemplate queueMessagingTemplate;
@Override
public void save(Sample sample) {
queueMessagingTemplate.convertAndSend(
"MynaviSampleSqsQueue", sample.getMessage());
}
}
[ポイント]SpringCloudAWSを使ったSQS Producer-Consumerアプリケーション
Consumer設定クラス
@Configuration
public class SqsConfig {
@Value("${queue.endpoint}")
private String queueEndpoint;
@Value("${cloud.aws.region.static}")
private String region;
@Autowired
AmazonSQSAsync amazonSQSAsync;
@Bean
public AwsClientBuilder.EndpointConfiguration endpointConfiguration(){
return new AwsClientBuilder.EndpointConfiguration(queueEndpoint, region);
}
}
[ポイント]SpringCloudAWSを使ったSQS Producer-Consumerアプリケーション
Consumer※このバッチ実行だとスレッドセーフでない&多重起動はできないので注意
@EnableSqs
public class MessageListener {
@Autowired
JobLauncher jobLauncher;
@Autowired
Job job;
@SqsListener(value = "MynaviSampleSqsQueue", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
public void onMessage(String message) throws
JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException, JobParametersInvalidException {
Map<String, JobParameter> jobParameterMap = new HashMap<>();
jobParameterMap.put("param", new JobParameter(message));
jobParameterMap.put("time", new JobParameter(System.currentTimeMillis()));
JobParameters jobParameters = new JobParameters(jobParameterMap);
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
ExecutionContext executionContext = jobExecution.getExecutionContext();
}
}
[補足]SQS Queueを刈り取って実行するSpring Batchのサンプルの処理イメージ


クラウドネイティブECSコンテナ編の環境でMSAアプリケーションを構築

クラウドネイティブECSコンテナ編の環境でMSAアプリケーションを構築
回避せよ!マイクロサービスの罠

タイヤのブランコ=「素早くアプリを作って、早くサービスを提供したい」なのか?
出典:「オレゴン大学の実験」(C.アレグザンダ―・他著,B6判,203p,鹿島出版会,1977年12月): よく分かる解説

[ポイント]SonarQubeServerをALB+ECS+RDSで構成のメリット
[補足]Spring.ioプロジェクトのSonarqubeプロジェクトはどうなっているか?


「テスト自動化の8原則」
[補足]Configパッケージは必要?
一連の連載でSpringBootプロジェクトでメイン起動クラスや設定クラスは全てconfigパッケージにまとめています。Bootのオートコンフィグレーション機能を考えると、起動クラスはパッケージのルートヒエラルキー配下に配置しておいた方がよいかもしれませんが、 複数人の開発では、設定クラスの配置に関して何かしらのルールを設けないと設定クラスが拡散し、パッケージ変更するだけでAPやテストが起動できなくなる事象に度々遭遇します。そのため本連載では、@SpringBootTestなどの一部のアノテーションは、ルートヒエラルキーに起動クラスがないと実行されないなど多少不便&推奨から外れたとしても明示的に設定クラスを指定しないと逆に動かないような構成にしています。

[ポイント]クラウド型CIツールのメリット

[ポイント]マイクロサービス間の連携テストはCDの中で自動化する

マルチOS・ブラウザでパラレル自動化テスト
[ポイント]ステージング環境とプロダクション環境のコンテナイメージは同一。AWS SysmtemsManagerで環境変数を切り替えるよう設定する。


