Sync docs from v1.0.0.RC2 to gh-pages
35
spring-cloud-kubernetes/1.0.0.RC2/css/highlight.css
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
code highlight CSS resemblign the Eclipse IDE default color schema
|
||||||
|
@author Costin Leau
|
||||||
|
*/
|
||||||
|
|
||||||
|
.hl-keyword {
|
||||||
|
color: #7F0055;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-comment {
|
||||||
|
color: #3F5F5F;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-multiline-comment {
|
||||||
|
color: #3F5FBF;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-tag {
|
||||||
|
color: #3F7F7F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-attribute {
|
||||||
|
color: #7F007F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-value {
|
||||||
|
color: #2A00FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-string {
|
||||||
|
color: #2A00FF;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
@IMPORT url("manual.css");
|
||||||
|
|
||||||
|
body.firstpage {
|
||||||
|
background: url("../images/background.png") no-repeat center top;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.part h1 {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@IMPORT url("manual.css");
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: url("../images/background.png") no-repeat center top;
|
||||||
|
}
|
||||||
|
|
||||||
344
spring-cloud-kubernetes/1.0.0.RC2/css/manual.css
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
@IMPORT url("highlight.css");
|
||||||
|
|
||||||
|
html {
|
||||||
|
padding: 0pt;
|
||||||
|
margin: 0pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: #333333;
|
||||||
|
margin: 15px 30px;
|
||||||
|
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: Consolas, "Liberation Mono", Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(a)>code {
|
||||||
|
color: #6D180B;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre)>code {
|
||||||
|
background-color: #F2F2F2;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 1px 3px 0;
|
||||||
|
text-shadow: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
body>*:first-child {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin: 0pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
background: #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3,h4,h5,h6 {
|
||||||
|
color: #000000;
|
||||||
|
cursor: text;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 30px 0 10px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3 {
|
||||||
|
margin: 40px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 70px 0 30px;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.part h1 {
|
||||||
|
border-top: 1px dotted #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h1 code {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2,h2 code {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3,h3 code {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,h1 code,h5,h5 code,h6,h6 code {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.book,div.chapter,div.appendix,div.part,div.preface {
|
||||||
|
min-width: 300px;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.releaseinfo {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.authorgroup {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.copyright {
|
||||||
|
line-height: 1;
|
||||||
|
margin-bottom: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legalnotice p {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.titlepage+p,div.titlepage+p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
line-height: 1.0;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #4183C4;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 15px 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,ol {
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table {
|
||||||
|
margin: 1em;
|
||||||
|
padding: 0.5em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table table,div.informaltable table {
|
||||||
|
display: table;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table td {
|
||||||
|
padding-left: 7px;
|
||||||
|
padding-right: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
line-height: 1.4;
|
||||||
|
padding: 0 20px;
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
border-radius: 3px 3px 3px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar p.title {
|
||||||
|
color: #6D180B;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.programlisting,pre.screen {
|
||||||
|
font-size: 15px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
border-radius: 3px 3px 3px 3px;
|
||||||
|
clear: both;
|
||||||
|
overflow: auto;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-family: Consolas, "Liberation Mono", Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
border: 1px solid #DDDDDD !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
border-collapse: separate !important;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
table thead {
|
||||||
|
background: #F5F5F5;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr {
|
||||||
|
border: none;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th,table td {
|
||||||
|
border: none !important;
|
||||||
|
padding: 6px 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr:nth-child(2n) {
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
}
|
||||||
|
|
||||||
|
td p {
|
||||||
|
margin: 0 0 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table-contents td p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
|
||||||
|
{
|
||||||
|
border: none !important;
|
||||||
|
background: none !important;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important p,div.note p,div.tip p,div.warning p {
|
||||||
|
color: #6F6F6F;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important code,div.note code,div.tip code,div.warning code {
|
||||||
|
background-color: #F2F2F2 !important;
|
||||||
|
border: 1px solid #CCCCCC !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
padding: 1px 3px 0 !important;
|
||||||
|
text-shadow: none !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note th,.tip th,.warning th {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
|
||||||
|
{
|
||||||
|
border-right: 1px solid #CCCCCC !important;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.calloutlist p,div.calloutlist td {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.calloutlist>table>tbody>tr>td:first-child {
|
||||||
|
padding-left: 10px;
|
||||||
|
width: 30px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important,div.note,div.tip,div.warning {
|
||||||
|
margin-left: 0px !important;
|
||||||
|
margin-right: 20px !important;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc {
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl,dt {
|
||||||
|
margin-top: 1px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc>dl>dt {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 30px 0 10px 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc>dl>dd>dl>dt {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 20px 0 10px 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc>dl>dd>dl>dd>dl>dt {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 20px;
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody.footnotes * {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footnote p {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footnote p sup {
|
||||||
|
margin-right: 6px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.navheader {
|
||||||
|
border-bottom: 1px solid #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.navfooter {
|
||||||
|
border-top: 1px solid #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-left: -1em;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title>a {
|
||||||
|
position: absolute;
|
||||||
|
visibility: hidden;
|
||||||
|
display: block;
|
||||||
|
font-size: 0.85em;
|
||||||
|
margin-top: 0.05em;
|
||||||
|
margin-left: -1em;
|
||||||
|
vertical-align: text-top;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title>a:before {
|
||||||
|
content: "\00A7";
|
||||||
|
}
|
||||||
|
|
||||||
|
.title:hover>a,.title>a:hover,.title:hover>a:hover {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title:focus>a,.title>a:focus,.title:focus>a:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
BIN
spring-cloud-kubernetes/1.0.0.RC2/images/background.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/images/callouts/1.png
Normal file
|
After Width: | Height: | Size: 329 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/images/callouts/2.png
Normal file
|
After Width: | Height: | Size: 353 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/images/callouts/3.png
Normal file
|
After Width: | Height: | Size: 350 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/images/caution.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/images/important.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/images/logo.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/images/note.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/images/tip.png
Normal file
|
After Width: | Height: | Size: 931 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/images/warning.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
117
spring-cloud-kubernetes/1.0.0.RC2/index.html
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="generator" content="Asciidoctor 1.5.7.1">
|
||||||
|
<title>spring-cloud-kubernetes</title>
|
||||||
|
<link rel="stylesheet" href="css/manual-singlepage.css">
|
||||||
|
<style>
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch {
|
||||||
|
border-width: 1px 1px 0 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #7a2518;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch--item {
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #7a2518;
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch--item.selected {
|
||||||
|
background-color: #7a2519;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script src="http://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function addBlockSwitches() {
|
||||||
|
$('.primary').each(function() {
|
||||||
|
primary = $(this);
|
||||||
|
createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
|
||||||
|
primary.children('.title').remove();
|
||||||
|
});
|
||||||
|
$('.secondary').each(function(idx, node) {
|
||||||
|
secondary = $(node);
|
||||||
|
primary = findPrimary(secondary);
|
||||||
|
switchItem = createSwitchItem(secondary, primary.children('.switch'));
|
||||||
|
switchItem.content.addClass('hidden');
|
||||||
|
findPrimary(secondary).append(switchItem.content);
|
||||||
|
secondary.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBlockSwitch(primary) {
|
||||||
|
blockSwitch = $('<div class="switch"></div>');
|
||||||
|
primary.prepend(blockSwitch);
|
||||||
|
return blockSwitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findPrimary(secondary) {
|
||||||
|
candidate = secondary.prev();
|
||||||
|
while (!candidate.is('.primary')) {
|
||||||
|
candidate = candidate.prev();
|
||||||
|
}
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSwitchItem(block, blockSwitch) {
|
||||||
|
blockName = block.children('.title').text();
|
||||||
|
content = block.children('.content').first().append(block.next('.colist'));
|
||||||
|
item = $('<div class="switch--item">' + blockName + '</div>');
|
||||||
|
item.on('click', '', content, function(e) {
|
||||||
|
$(this).addClass('selected');
|
||||||
|
$(this).siblings().removeClass('selected');
|
||||||
|
e.data.siblings('.content').addClass('hidden');
|
||||||
|
e.data.removeClass('hidden');
|
||||||
|
});
|
||||||
|
blockSwitch.append(item);
|
||||||
|
return {'item': item, 'content': content};
|
||||||
|
}
|
||||||
|
|
||||||
|
$(addBlockSwitches);
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="article">
|
||||||
|
<div id="header">
|
||||||
|
<h1>spring-cloud-kubernetes</h1>
|
||||||
|
</div>
|
||||||
|
<div id="content">
|
||||||
|
<div id="preamble">
|
||||||
|
<div class="sectionbody">
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>1.0.0.RC2</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sect1">
|
||||||
|
<h2 id="_pick_the_documentation_option">Pick The Documentation Option</h2>
|
||||||
|
<div class="sectionbody">
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p><a href="single/spring-cloud-kubernetes.html">Single HTML</a></p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><a href="multi/multi_spring-cloud-kubernetes.html">Multi HTML</a></p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
|
||||||
|
<script>prettyPrint()</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
35
spring-cloud-kubernetes/1.0.0.RC2/multi/css/highlight.css
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
code highlight CSS resemblign the Eclipse IDE default color schema
|
||||||
|
@author Costin Leau
|
||||||
|
*/
|
||||||
|
|
||||||
|
.hl-keyword {
|
||||||
|
color: #7F0055;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-comment {
|
||||||
|
color: #3F5F5F;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-multiline-comment {
|
||||||
|
color: #3F5FBF;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-tag {
|
||||||
|
color: #3F7F7F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-attribute {
|
||||||
|
color: #7F007F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-value {
|
||||||
|
color: #2A00FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-string {
|
||||||
|
color: #2A00FF;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
@IMPORT url("manual.css");
|
||||||
|
|
||||||
|
body.firstpage {
|
||||||
|
background: url("../images/background.png") no-repeat center top;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.part h1 {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@IMPORT url("manual.css");
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: url("../images/background.png") no-repeat center top;
|
||||||
|
}
|
||||||
|
|
||||||
344
spring-cloud-kubernetes/1.0.0.RC2/multi/css/manual.css
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
@IMPORT url("highlight.css");
|
||||||
|
|
||||||
|
html {
|
||||||
|
padding: 0pt;
|
||||||
|
margin: 0pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: #333333;
|
||||||
|
margin: 15px 30px;
|
||||||
|
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: Consolas, "Liberation Mono", Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(a)>code {
|
||||||
|
color: #6D180B;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre)>code {
|
||||||
|
background-color: #F2F2F2;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 1px 3px 0;
|
||||||
|
text-shadow: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
body>*:first-child {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin: 0pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
background: #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3,h4,h5,h6 {
|
||||||
|
color: #000000;
|
||||||
|
cursor: text;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 30px 0 10px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3 {
|
||||||
|
margin: 40px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 70px 0 30px;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.part h1 {
|
||||||
|
border-top: 1px dotted #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h1 code {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2,h2 code {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3,h3 code {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,h1 code,h5,h5 code,h6,h6 code {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.book,div.chapter,div.appendix,div.part,div.preface {
|
||||||
|
min-width: 300px;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.releaseinfo {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.authorgroup {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.copyright {
|
||||||
|
line-height: 1;
|
||||||
|
margin-bottom: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legalnotice p {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.titlepage+p,div.titlepage+p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
line-height: 1.0;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #4183C4;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 15px 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,ol {
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table {
|
||||||
|
margin: 1em;
|
||||||
|
padding: 0.5em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table table,div.informaltable table {
|
||||||
|
display: table;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table td {
|
||||||
|
padding-left: 7px;
|
||||||
|
padding-right: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
line-height: 1.4;
|
||||||
|
padding: 0 20px;
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
border-radius: 3px 3px 3px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar p.title {
|
||||||
|
color: #6D180B;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.programlisting,pre.screen {
|
||||||
|
font-size: 15px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
border-radius: 3px 3px 3px 3px;
|
||||||
|
clear: both;
|
||||||
|
overflow: auto;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-family: Consolas, "Liberation Mono", Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
border: 1px solid #DDDDDD !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
border-collapse: separate !important;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
table thead {
|
||||||
|
background: #F5F5F5;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr {
|
||||||
|
border: none;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th,table td {
|
||||||
|
border: none !important;
|
||||||
|
padding: 6px 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr:nth-child(2n) {
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
}
|
||||||
|
|
||||||
|
td p {
|
||||||
|
margin: 0 0 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table-contents td p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
|
||||||
|
{
|
||||||
|
border: none !important;
|
||||||
|
background: none !important;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important p,div.note p,div.tip p,div.warning p {
|
||||||
|
color: #6F6F6F;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important code,div.note code,div.tip code,div.warning code {
|
||||||
|
background-color: #F2F2F2 !important;
|
||||||
|
border: 1px solid #CCCCCC !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
padding: 1px 3px 0 !important;
|
||||||
|
text-shadow: none !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note th,.tip th,.warning th {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
|
||||||
|
{
|
||||||
|
border-right: 1px solid #CCCCCC !important;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.calloutlist p,div.calloutlist td {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.calloutlist>table>tbody>tr>td:first-child {
|
||||||
|
padding-left: 10px;
|
||||||
|
width: 30px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important,div.note,div.tip,div.warning {
|
||||||
|
margin-left: 0px !important;
|
||||||
|
margin-right: 20px !important;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc {
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl,dt {
|
||||||
|
margin-top: 1px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc>dl>dt {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 30px 0 10px 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc>dl>dd>dl>dt {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 20px 0 10px 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc>dl>dd>dl>dd>dl>dt {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 20px;
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody.footnotes * {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footnote p {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footnote p sup {
|
||||||
|
margin-right: 6px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.navheader {
|
||||||
|
border-bottom: 1px solid #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.navfooter {
|
||||||
|
border-top: 1px solid #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-left: -1em;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title>a {
|
||||||
|
position: absolute;
|
||||||
|
visibility: hidden;
|
||||||
|
display: block;
|
||||||
|
font-size: 0.85em;
|
||||||
|
margin-top: 0.05em;
|
||||||
|
margin-left: -1em;
|
||||||
|
vertical-align: text-top;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title>a:before {
|
||||||
|
content: "\00A7";
|
||||||
|
}
|
||||||
|
|
||||||
|
.title:hover>a,.title>a:hover,.title:hover>a:hover {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title:focus>a,.title>a:focus,.title:focus>a:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
BIN
spring-cloud-kubernetes/1.0.0.RC2/multi/images/background.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/multi/images/callouts/1.png
Normal file
|
After Width: | Height: | Size: 329 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/multi/images/callouts/2.png
Normal file
|
After Width: | Height: | Size: 353 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/multi/images/callouts/3.png
Normal file
|
After Width: | Height: | Size: 350 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/multi/images/caution.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/multi/images/important.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/multi/images/logo.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/multi/images/note.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/multi/images/tip.png
Normal file
|
After Width: | Height: | Size: 931 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/multi/images/warning.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
47
spring-cloud-kubernetes/1.0.0.RC2/multi/multi__building.html
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>12. Building</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__other_resources.html" title="11. Other Resources"><link rel="next" href="multi__contributing.html" title="13. Contributing"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">12. Building</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__other_resources.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__contributing.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_building" href="#_building"></a>12. Building</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_basic_compile_and_test" href="#_basic_compile_and_test"></a>12.1 Basic Compile and Test</h2></div></div></div><p>To build the source you will need to install JDK 1.7.</p><p>Spring Cloud uses Maven for most build-related activities, and you
|
||||||
|
should be able to get off the ground quite quickly by cloning the
|
||||||
|
project you are interested in and typing</p><pre class="screen">$ ./mvnw install</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>You can also install Maven (>=3.3.3) yourself and run the <code class="literal">mvn</code> command
|
||||||
|
in place of <code class="literal">./mvnw</code> in the examples below. If you do that you also
|
||||||
|
might need to add <code class="literal">-P spring</code> if your local Maven settings do not
|
||||||
|
contain repository declarations for spring pre-release artifacts.</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Be aware that you might need to increase the amount of memory
|
||||||
|
available to Maven by setting a <code class="literal">MAVEN_OPTS</code> environment variable with
|
||||||
|
a value like <code class="literal">-Xmx512m -XX:MaxPermSize=128m</code>. We try to cover this in
|
||||||
|
the <code class="literal">.mvn</code> configuration, so if you find you have to do it to make a
|
||||||
|
build succeed, please raise a ticket to get the settings added to
|
||||||
|
source control.</p></td></tr></table></div><p>For hints on how to build the project look in <code class="literal">.travis.yml</code> if there
|
||||||
|
is one. There should be a "script" and maybe "install" command. Also
|
||||||
|
look at the "services" section to see if any services need to be
|
||||||
|
running locally (e.g. mongo or rabbit). Ignore the git-related bits
|
||||||
|
that you might find in "before_install" since they’re related to setting git
|
||||||
|
credentials and you already have those.</p><p>The projects that require middleware generally include a
|
||||||
|
<code class="literal">docker-compose.yml</code>, so consider using
|
||||||
|
<a class="link" href="http://compose.docker.io/" target="_top">Docker Compose</a> to run the middeware servers
|
||||||
|
in Docker containers. See the README in the
|
||||||
|
<a class="link" href="https://github.com/spring-cloud-samples/scripts" target="_top">scripts demo
|
||||||
|
repository</a> for specific instructions about the common cases of mongo,
|
||||||
|
rabbit and redis.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>If all else fails, build with the command from <code class="literal">.travis.yml</code> (usually
|
||||||
|
<code class="literal">./mvnw install</code>).</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_documentation" href="#_documentation"></a>12.2 Documentation</h2></div></div></div><p>The spring-cloud-build module has a "docs" profile, and if you switch
|
||||||
|
that on it will try to build asciidoc sources from
|
||||||
|
<code class="literal">src/main/asciidoc</code>. As part of that process it will look for a
|
||||||
|
<code class="literal">README.adoc</code> and process it by loading all the includes, but not
|
||||||
|
parsing or rendering it, just copying it to <code class="literal">${main.basedir}</code>
|
||||||
|
(defaults to <code class="literal">${basedir}</code>, i.e. the root of the project). If there are
|
||||||
|
any changes in the README it will then show up after a Maven build as
|
||||||
|
a modified file in the correct place. Just commit it and push the change.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_working_with_the_code" href="#_working_with_the_code"></a>12.3 Working with the code</h2></div></div></div><p>If you don’t have an IDE preference we would recommend that you use
|
||||||
|
<a class="link" href="http://www.springsource.com/developer/sts" target="_top">Spring Tools Suite</a> or
|
||||||
|
<a class="link" href="http://eclipse.org" target="_top">Eclipse</a> when working with the code. We use the
|
||||||
|
<a class="link" href="http://eclipse.org/m2e/" target="_top">m2eclipse</a> eclipse plugin for maven support. Other IDEs and tools
|
||||||
|
should also work without issue as long as they use Maven 3.3.3 or better.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_importing_into_eclipse_with_m2eclipse" href="#_importing_into_eclipse_with_m2eclipse"></a>12.3.1 Importing into eclipse with m2eclipse</h3></div></div></div><p>We recommend the <a class="link" href="http://eclipse.org/m2e/" target="_top">m2eclipse</a> eclipse plugin when working with
|
||||||
|
eclipse. If you don’t already have m2eclipse installed it is available from the "eclipse
|
||||||
|
marketplace".</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Older versions of m2e do not support Maven 3.3, so once the
|
||||||
|
projects are imported into Eclipse you will also need to tell
|
||||||
|
m2eclipse to use the right profile for the projects. If you
|
||||||
|
see many different errors related to the POMs in the projects, check
|
||||||
|
that you have an up to date installation. If you can’t upgrade m2e,
|
||||||
|
add the "spring" profile to your <code class="literal">settings.xml</code>. Alternatively you can
|
||||||
|
copy the repository settings from the "spring" profile of the parent
|
||||||
|
pom into your <code class="literal">settings.xml</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_importing_into_eclipse_without_m2eclipse" href="#_importing_into_eclipse_without_m2eclipse"></a>12.3.2 Importing into eclipse without m2eclipse</h3></div></div></div><p>If you prefer not to use m2eclipse you can generate eclipse project metadata using the
|
||||||
|
following command:</p><pre class="screen">$ ./mvnw eclipse:eclipse</pre><p>The generated eclipse projects can be imported by selecting <code class="literal">import existing projects</code>
|
||||||
|
from the <code class="literal">file</code> menu.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__other_resources.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__contributing.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">11. Other Resources </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 13. Contributing</td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>13. Contributing</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__building.html" title="12. Building"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">13. Contributing</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__building.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> </td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_contributing" href="#_contributing"></a>13. Contributing</h1></div></div></div><p>Spring Cloud is released under the non-restrictive Apache 2.0 license,
|
||||||
|
and follows a very standard Github development process, using Github
|
||||||
|
tracker for issues and merging pull requests into master. If you want
|
||||||
|
to contribute even something trivial please do not hesitate, but
|
||||||
|
follow the guidelines below.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_sign_the_contributor_license_agreement" href="#_sign_the_contributor_license_agreement"></a>13.1 Sign the Contributor License Agreement</h2></div></div></div><p>Before we accept a non-trivial patch or pull request we will need you to sign the
|
||||||
|
<a class="link" href="https://cla.pivotal.io/sign/spring" target="_top">Contributor License Agreement</a>.
|
||||||
|
Signing the contributor’s agreement does not grant anyone commit rights to the main
|
||||||
|
repository, but it does mean that we can accept your contributions, and you will get an
|
||||||
|
author credit if we do. Active contributors might be asked to join the core team, and
|
||||||
|
given the ability to merge pull requests.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_code_of_conduct" href="#_code_of_conduct"></a>13.2 Code of Conduct</h2></div></div></div><p>This project adheres to the Contributor Covenant <a class="link" href="https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc" target="_top">code of
|
||||||
|
conduct</a>. By participating, you are expected to uphold this code. Please report
|
||||||
|
unacceptable behavior to <a class="link" href="mailto:spring-code-of-conduct@pivotal.io" target="_top">spring-code-of-conduct@pivotal.io</a>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_code_conventions_and_housekeeping" href="#_code_conventions_and_housekeeping"></a>13.3 Code Conventions and Housekeeping</h2></div></div></div><p>None of these is essential for a pull request, but they will all help. They can also be
|
||||||
|
added after the original pull request but before a merge.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Use the Spring Framework code format conventions. If you use Eclipse
|
||||||
|
you can import formatter settings using the
|
||||||
|
<code class="literal">eclipse-code-formatter.xml</code> file from the
|
||||||
|
<a class="link" href="https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml" target="_top">Spring
|
||||||
|
Cloud Build</a> project. If using IntelliJ, you can use the
|
||||||
|
<a class="link" href="http://plugins.jetbrains.com/plugin/6546" target="_top">Eclipse Code Formatter
|
||||||
|
Plugin</a> to import the same file.</li><li class="listitem">Make sure all new <code class="literal">.java</code> files to have a simple Javadoc class comment with at least an
|
||||||
|
<code class="literal">@author</code> tag identifying you, and preferably at least a paragraph on what the class is
|
||||||
|
for.</li><li class="listitem">Add the ASF license header comment to all new <code class="literal">.java</code> files (copy from existing files
|
||||||
|
in the project)</li><li class="listitem">Add yourself as an <code class="literal">@author</code> to the .java files that you modify substantially (more
|
||||||
|
than cosmetic changes).</li><li class="listitem">Add some Javadocs and, if you change the namespace, some XSD doc elements.</li><li class="listitem">A few unit tests would help a lot as well — someone has to do it.</li><li class="listitem">If no-one else is using your branch, please rebase it against the current master (or
|
||||||
|
other target branch in the main project).</li><li class="listitem">When writing a commit message please follow <a class="link" href="http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html" target="_top">these conventions</a>,
|
||||||
|
if you are fixing an existing issue please add <code class="literal">Fixes gh-XXXX</code> at the end of the commit
|
||||||
|
message (where XXXX is the issue number).</li></ul></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__building.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> </td></tr><tr><td width="40%" align="left" valign="top">12. Building </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> </td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>2. DiscoveryClient for Kubernetes</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__why_do_you_need_spring_cloud_kubernetes.html" title="1. Why do you need Spring Cloud Kubernetes?"><link rel="next" href="multi__kubernetes_native_service_discovery.html" title="3. Kubernetes native service discovery"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">2. DiscoveryClient for Kubernetes</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__why_do_you_need_spring_cloud_kubernetes.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__kubernetes_native_service_discovery.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_discoveryclient_for_kubernetes" href="#_discoveryclient_for_kubernetes"></a>2. DiscoveryClient for Kubernetes</h1></div></div></div><p>This project provides an implementation of <a class="link" href="https://github.com/spring-cloud/spring-cloud-commons/blob/master/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/DiscoveryClient.java" target="_top">Discovery Client</a>
|
||||||
|
for <a class="link" href="http://kubernetes.io" target="_top">Kubernetes</a>.
|
||||||
|
This allows you to query Kubernetes endpoints <span class="strong"><strong>(see <a class="link" href="http://kubernetes.io/docs/user-guide/services/" target="_top">services</a>)</strong></span> by name.
|
||||||
|
A service is typically exposed by the Kubernetes API server as a collection of endpoints which represent <code class="literal">http</code>, <code class="literal">https</code> addresses that a client can
|
||||||
|
access from a Spring Boot application running as a pod. This discovery feature is also used by the Spring Cloud Kubernetes Ribbon project
|
||||||
|
to fetch the list of the endpoints defined for an application to be load balanced.</p><p>This is something that you get for free just by adding the following dependency inside your project:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-kubernetes<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${latest.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>To enable loading of the <code class="literal">DiscoveryClient</code>, add <code class="literal">@EnableDiscoveryClient</code> to the according configuration or application class like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
|
||||||
|
<em><span class="hl-annotation" style="color: gray">@EnableDiscoveryClient</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> main(String[] args) {
|
||||||
|
SpringApplication.run(Application.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, args);
|
||||||
|
}
|
||||||
|
}</pre><p>Then you can inject the client in your code simply by:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> DiscoveryClient discoveryClient;</pre><p>If for any reason you need to disable the <code class="literal">DiscoveryClient</code> you can simply set the following property in <code class="literal">application.properties</code>:</p><pre class="screen">spring.cloud.kubernetes.discovery.enabled=false</pre><p>Some Spring Cloud components use the <code class="literal">DiscoveryClient</code> in order to obtain info about the local service instance. For
|
||||||
|
this to work you need to align the Kubernetes service name with the <code class="literal">spring.application.name</code> property.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__why_do_you_need_spring_cloud_kubernetes.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__kubernetes_native_service_discovery.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">1. Why do you need Spring Cloud Kubernetes? </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 3. Kubernetes native service discovery</td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>10. Examples</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__security_configurations_inside_kubernetes.html" title="9. Security Configurations inside Kubernetes"><link rel="next" href="multi__other_resources.html" title="11. Other Resources"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">10. Examples</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__security_configurations_inside_kubernetes.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__other_resources.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_examples" href="#_examples"></a>10. Examples</h1></div></div></div><p>Spring Cloud Kubernetes tries to make it transparent for your applications to consume Kubernetes Native Services
|
||||||
|
following the Spring Cloud interfaces.</p><p>In your applications, you need to add the <span class="strong"><strong>spring-cloud-kubernetes-discovery</strong></span> dependency to your classpath and remove any other dependency that contains a <span class="strong"><strong>DiscoveryClient</strong></span> implementation (ie. Eureka Discovery Client).
|
||||||
|
The same applies for PropertySourceLocator, where you need to add to the classpath the <span class="strong"><strong>spring-cloud-kubernetes-config</strong></span> and remove any other dependency that contains a <span class="strong"><strong>PropertySourceLocator</strong></span> implementation (ie. Config Server Client).</p><p>The following projects highlight the usage of these dependencies and demonstrate how these libraries can be used from any Spring Boot application.</p><p>List of examples using these projects:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="https://github.com/spring-cloud/spring-cloud-kubernetes/tree/master/spring-cloud-kubernetes-examples" target="_top">Spring Cloud Kubernetes Examples</a>: the ones located inside this repository.</li><li class="listitem">Spring Cloud Kubernetes Full Example: Minions and Boss</li><li class="listitem"><a class="link" href="https://github.com/salaboy/spring-cloud-k8s-minion" target="_top">Minion</a></li><li class="listitem"><a class="link" href="https://github.com/salaboy/spring-cloud-k8s-boss" target="_top">Boss</a></li><li class="listitem">Spring Cloud Kubernetes Full Example: <a class="link" href="https://github.com/salaboy/s1p_docs" target="_top">SpringOne Platform Tickets Service</a></li><li class="listitem"><a class="link" href="https://github.com/salaboy/s1p_gateway" target="_top">Spring Cloud Gateway with Spring Cloud Kubernetes Discovery and Config</a></li><li class="listitem"><a class="link" href="https://github.com/salaboy/showcase-admin-tool" target="_top">Spring Boot Admin with Spring Cloud Kubernetes Discovery and Config</a></li></ul></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__security_configurations_inside_kubernetes.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__other_resources.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">9. Security Configurations inside Kubernetes </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 11. Other Resources</td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>6. Kubernetes Ecosystem Awareness</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__ribbon_discovery_in_kubernetes.html" title="5. Ribbon discovery in Kubernetes"><link rel="next" href="multi__pod_health_indicator.html" title="7. Pod Health Indicator"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6. Kubernetes Ecosystem Awareness</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__ribbon_discovery_in_kubernetes.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__pod_health_indicator.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_kubernetes_ecosystem_awareness" href="#_kubernetes_ecosystem_awareness"></a>6. Kubernetes Ecosystem Awareness</h1></div></div></div><p>All of the features described above will work equally well regardless of whether your application is running inside
|
||||||
|
Kubernetes or not. This is really helpful for development and troubleshooting.
|
||||||
|
From a development point of view, this is really helpful as you can start your Spring Boot application and debug one
|
||||||
|
of the modules part of this project. It is not required to deploy it in Kubernetes
|
||||||
|
as the code of the project relies on the
|
||||||
|
<a class="link" href="https://github.com/fabric8io/kubernetes-client" target="_top">Fabric8 Kubernetes Java client</a> which is a fluent DSL able to
|
||||||
|
communicate using <code class="literal">http</code> protocol to the REST API of Kubernetes Server.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_kubernetes_profile_autoconfiguration" href="#_kubernetes_profile_autoconfiguration"></a>6.1 Kubernetes Profile Autoconfiguration</h2></div></div></div><p>When the application runs as a pod inside Kubernetes a Spring profile named <code class="literal">kubernetes</code> will automatically get activated.
|
||||||
|
This allows the developer to customize the configuration, to define beans that will be applied when the Spring Boot application is deployed
|
||||||
|
within the Kubernetes platform <span class="strong"><strong>(e.g. different dev and prod configuration)</strong></span>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_istio_awareness" href="#_istio_awareness"></a>6.2 Istio Awareness</h2></div></div></div><p>When including the <span class="strong"><strong>spring-cloud-kubernetes-istio</strong></span> module into the application classpath a new profile will be added to the application,
|
||||||
|
if the application is running inside a Kubernetes Cluster with <a class="link" href="http://istio.io" target="_top">Istio</a> installed. Then you can use
|
||||||
|
spring <span class="strong"><strong>@Profile("istio")</strong></span> annotations into your Beans and <span class="strong"><strong>@Configuration</strong></span>'s.</p><p>The Istio awareness module uses the <span class="strong"><strong>me.snowdrop:istio-client</strong></span> to interact with Istio APIs enabling us to discover traffic rules, circuit breakers, etc.
|
||||||
|
Making it easy for our Spring Boot applications to consume this data to dynamically configure themselves according the environment.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__ribbon_discovery_in_kubernetes.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__pod_health_indicator.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Ribbon discovery in Kubernetes </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 7. Pod Health Indicator</td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>3. Kubernetes native service discovery</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__discoveryclient_for_kubernetes.html" title="2. DiscoveryClient for Kubernetes"><link rel="next" href="multi__kubernetes_propertysource_implementations.html" title="4. Kubernetes PropertySource implementations"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3. Kubernetes native service discovery</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__discoveryclient_for_kubernetes.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__kubernetes_propertysource_implementations.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_kubernetes_native_service_discovery" href="#_kubernetes_native_service_discovery"></a>3. Kubernetes native service discovery</h1></div></div></div><p>Kubernetes itself is capable of (server side) service discovery (see: <a class="link" href="https://kubernetes.io/docs/concepts/services-networking/service/#discovering-services" target="_top">https://kubernetes.io/docs/concepts/services-networking/service/#discovering-services</a>).
|
||||||
|
Using native kubernetes service discovery ensures compatibility with additional tooling, like: istio <a class="link" href="https://istio.io" target="_top">https://istio.io</a> (service mesh, capable of load balancing, ribbon, circuit breaker, failover and much more).</p><p>The caller service just needs to refer to names resolvable in particular kubernetes cluster then. Simplest implementation might use the spring <code class="literal">RestTemplate</code> referring to fully qualified domain name (FQDN) <code class="literal"><a class="link" href="http://{service-name}.{namespace}.svc.{cluster}.local:{service-port}" target="_top">http://{service-name}.{namespace}.svc.{cluster}.local:{service-port}</a></code>.</p><p>Additionally, hystrix can be used for:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">circuit breaker implementation on the caller side, just by annotating the spring boot application class: <code class="literal">@EnableCircuitBreaker</code></li><li class="listitem">and for the fallback functionality, annotating the respective method via: <code class="literal">@HystrixCommand(fallbackMethod=</code> does the job.</li></ul></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__discoveryclient_for_kubernetes.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__kubernetes_propertysource_implementations.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2. DiscoveryClient for Kubernetes </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 4. Kubernetes PropertySource implementations</td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>4. Kubernetes PropertySource implementations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__kubernetes_native_service_discovery.html" title="3. Kubernetes native service discovery"><link rel="next" href="multi__ribbon_discovery_in_kubernetes.html" title="5. Ribbon discovery in Kubernetes"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4. Kubernetes PropertySource implementations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__kubernetes_native_service_discovery.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__ribbon_discovery_in_kubernetes.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_kubernetes_propertysource_implementations" href="#_kubernetes_propertysource_implementations"></a>4. Kubernetes PropertySource implementations</h1></div></div></div><p>The most common approach to configure your Spring Boot application is to create an <code class="literal">application.properties|yaml</code> or
|
||||||
|
an <code class="literal">application-profile.properties|yaml</code> file containing key-value pairs providing customization values to your
|
||||||
|
application or Spring Boot starters. Users may override these properties by specifying system properties or environment
|
||||||
|
variables.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_configmap_propertysource" href="#_configmap_propertysource"></a>4.1 ConfigMap PropertySource</h2></div></div></div><p>Kubernetes provides a resource named <a class="link" href="http://kubernetes.io/docs/user-guide/configmap/" target="_top">ConfigMap</a> to externalize the
|
||||||
|
parameters to pass to your application in the form of key-value pairs or embedded <code class="literal">application.properties|yaml</code> files.
|
||||||
|
The <a class="link" href="./spring-cloud-kubernetes-config" target="_top">Spring Cloud Kubernetes Config</a> project makes Kubernetes `ConfigMap`s available
|
||||||
|
during application bootstrapping and triggers hot reloading of beans or Spring context when changes are detected on
|
||||||
|
observed `ConfigMap`s.</p><p>The default behavior is to create a <code class="literal">ConfigMapPropertySource</code> based on a Kubernetes <code class="literal">ConfigMap</code> which has <code class="literal">metadata.name</code> of either the name of
|
||||||
|
your Spring application (as defined by its <code class="literal">spring.application.name</code> property) or a custom name defined within the
|
||||||
|
<code class="literal">bootstrap.properties</code> file under the following key <code class="literal">spring.cloud.kubernetes.config.name</code>.</p><p>However, more advanced configuration are possible where multiple ConfigMaps can be used
|
||||||
|
This is made possible by the <code class="literal">spring.cloud.kubernetes.config.sources</code> list.
|
||||||
|
For example one could define the following ConfigMaps</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> application</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: cloud-k8s-app
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> cloud</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> kubernetes</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> config</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: default-name
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> namespace</span>: default-namespace
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> sources</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Spring Cloud Kubernetes will lookup a ConfigMap named c1 in namespace default-namespace</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - name</span>: c1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Spring Cloud Kubernetes will lookup a ConfigMap named default-name in whatever namespace n2</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - namespace</span>: n2
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Spring Cloud Kubernetes will lookup a ConfigMap named c3 in namespace n3</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - namespace</span>: n3
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: c3</pre><p>In the example above, it <code class="literal">spring.cloud.kubernetes.config.namespace</code> had not been set,
|
||||||
|
then the ConfigMap named <code class="literal">c1</code> would be looked up in the namespace that the application runs</p><p>Any matching <code class="literal">ConfigMap</code> that is found, will be processed as follows:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">apply individual configuration properties.</li><li class="listitem">apply as <code class="literal">yaml</code> the content of any property named <code class="literal">application.yaml</code></li><li class="listitem">apply as properties file the content of any property named <code class="literal">application.properties</code></li></ul></div><p>The single exception to the aforementioned flow is when the <code class="literal">ConfigMap</code> contains a <span class="strong"><strong>single</strong></span> key that indicates
|
||||||
|
the file is a YAML or Properties file. In that case the name of the key does NOT have to be <code class="literal">application.yaml</code> or
|
||||||
|
<code class="literal">application.properties</code> (it can be anything) and the value of the property will be treated correctly.
|
||||||
|
This features facilitates the use case where the <code class="literal">ConfigMap</code> was created using something like:</p><p><code class="literal">kubectl create configmap game-config --from-file=/path/to/app-config.yaml</code></p><p>Example:</p><p>Let’s assume that we have a Spring Boot application named <code class="literal">demo</code> that uses properties to read its thread pool
|
||||||
|
configuration.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">pool.size.core</code></li><li class="listitem"><code class="literal">pool.size.maximum</code></li></ul></div><p>This can be externalized to config map in <code class="literal">yaml</code> format:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: ConfigMap
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">metadata</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: demo
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">data</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> pool.size.core</span>: <span class="hl-number">1</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> pool.size.max</span>: <span class="hl-number">16</span></pre><p>Individual properties work fine for most cases but sometimes embedded <code class="literal">yaml</code> is more convenient. In this case we will
|
||||||
|
use a single property named <code class="literal">application.yaml</code> to embed our <code class="literal">yaml</code>:</p><pre class="literallayout"> ```yaml
|
||||||
|
kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: demo
|
||||||
|
data:
|
||||||
|
application.yaml: |-
|
||||||
|
pool:
|
||||||
|
size:
|
||||||
|
core: 1
|
||||||
|
max:16</pre><pre class="screen">The following also works:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: demo
|
||||||
|
data:
|
||||||
|
custom-name.yaml: |-
|
||||||
|
pool:
|
||||||
|
size:
|
||||||
|
core: 1
|
||||||
|
max:16</pre><p>Spring Boot applications can also be configured differently depending on active profiles which will be merged together
|
||||||
|
when the ConfigMap is read. It is possible to provide different property values for different profiles using an
|
||||||
|
<code class="literal">application.properties|yaml</code> property, specifying profile-specific values each in their own document
|
||||||
|
(indicated by the <code class="literal">---</code> sequence) as follows:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: ConfigMap
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">metadata</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: demo
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">data</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> application.yml</span>: |-
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> greeting</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Hello to the World
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> farewell</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Goodbye
|
||||||
|
---
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> spring</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> profiles</span>: development
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> greeting</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Hello to the Developers
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> farewell</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Goodbye to the Developers
|
||||||
|
---
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> spring</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> profiles</span>: production
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> greeting</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Hello to the Ops</pre><p>In the above case, the configuration loaded into your Spring Application with the <code class="literal">development</code> profile will be:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> greeting</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Hello to the Developers
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> farewell</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Goodbye to the Developers</pre><p>whereas if the <code class="literal">production</code> profile is active, the configuration will be:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> greeting</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Hello to the Ops
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> farewell</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Goodbye</pre><p>If both profiles are active, the property which appears last within the configmap will overwrite preceding values.</p><p>To tell to Spring Boot which <code class="literal">profile</code> should be enabled at bootstrap, a system property can be passed to the Java
|
||||||
|
command launching your Spring Boot application using an env variable that you will define with the OpenShift
|
||||||
|
<code class="literal">DeploymentConfig</code> or Kubernetes <code class="literal">ReplicationConfig</code> resource file as follows:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: DeploymentConfig
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spec</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> replicas</span>: <span class="hl-number">1</span>
|
||||||
|
...
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> spec</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> containers</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - env</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - name</span>: JAVA_APP_DIR
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> value</span>: /deployments
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - name</span>: JAVA_OPTIONS
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> value</span>: -Dspring.profiles.active=developer</pre><p><span class="strong"><strong>Notes:</strong></span>
|
||||||
|
- check the security configuration section, to access config maps from inside a pod you need to have the correct
|
||||||
|
Kubernetes service accounts, roles and role bindings.</p><p>Another option for using ConfigMaps, is to mount them into the Pod running the Spring Cloud Kubernetes application
|
||||||
|
and have Spring Cloud Kubernetes read them from the file system.
|
||||||
|
This behavior is controlled by the <code class="literal">spring.cloud.kubernetes.config.paths</code> property and can be used in
|
||||||
|
addition to or instead of the mechanism described earlier.
|
||||||
|
Multiple (exact) file paths can be specified in <code class="literal">spring.cloud.kubernetes.config.paths</code> by using the <code class="literal">,</code> delimiter</p><div class="table"><a name="d0e301" href="#d0e301"></a><p class="title"><b>Table 4.1. Properties:</b></p><div class="table-contents"><table class="table" summary="Properties:" style="border-collapse: collapse;border-top: 1px solid ; border-bottom: 1px solid ; border-left: 1px solid ; border-right: 1px solid ; "><colgroup><col class="col_1"><col class="col_2"><col class="col_3"><col class="col_4"></colgroup><thead><tr><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Name</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Type</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Default</th><th style="border-bottom: 1px solid ; " align="left" valign="top">Description</th></tr></thead><tfoot><tr><th style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.config.enableApi</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>Boolean</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>true</p></th><th style="" align="left" valign="top"><p>Enable/Disable consuming ConfigMaps via APIs</p></th></tr></tfoot><tbody><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.config.enabled</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Boolean</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>true</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Enable Secrets PropertySource</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.config.name</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>String</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>${spring.application.name}</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Sets the name of ConfigMap to lookup</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.config.namespace</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>String</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Client namespace</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Sets the Kubernetes namespace where to lookup</p></td></tr><tr><td style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.config.paths</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>List</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>null</p></td><td style="" align="left" valign="top"><p>Sets the paths where ConfigMaps are mounted</p></td></tr></tbody></table></div></div><br class="table-break"></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_secrets_propertysource" href="#_secrets_propertysource"></a>4.2 Secrets PropertySource</h2></div></div></div><p>Kubernetes has the notion of [Secrets](<a class="link" href="https://kubernetes.io/docs/concepts/configuration/secret/" target="_top">https://kubernetes.io/docs/concepts/configuration/secret/</a>) for storing
|
||||||
|
sensitive data such as password, OAuth tokens, etc. This project provides integration with <code class="literal">Secrets</code> to make secrets
|
||||||
|
accessible by Spring Boot applications. This feature can be explicitly enabled/disabled using the <code class="literal">spring.cloud.kubernetes.secrets.enabled</code> property.</p><p>The <code class="literal">SecretsPropertySource</code> when enabled will lookup Kubernetes for <code class="literal">Secrets</code> from the following sources:
|
||||||
|
1. reading recursively from secrets mounts
|
||||||
|
2. named after the application (as defined by <code class="literal">spring.application.name</code>)
|
||||||
|
3. matching some labels</p><p>Please note that by default, consuming Secrets via API (points 2 and 3 above) <span class="strong"><strong>is not enabled</strong></span> for security reasons
|
||||||
|
and it is recommend that containers share secrets via mounted volumes. Otherwise proper RBAC security configurations must be provided
|
||||||
|
to make sure that unauthorized access to Secrets occurs.</p><p>If the secrets are found their data is made available to the application.</p><p><span class="strong"><strong>Example:</strong></span></p><p>Let’s assume that we have a spring boot application named <code class="literal">demo</code> that uses properties to read its database
|
||||||
|
configuration. We can create a Kubernetes secret using the following command:</p><pre class="screen">oc create secret generic db-secret --from-literal=username=user --from-literal=password=p455w0rd</pre><p>This would create the following secret (shown using <code class="literal">oc get secrets db-secret -o yaml</code>):</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">data</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> password</span>: cDQ1NXcwcmQ=
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> username</span>: dXNlcg==
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: Secret
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">metadata</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> creationTimestamp</span>: <span class="hl-number">2017</span>-<span class="hl-number">07</span>-<span class="hl-number">04</span>T09:<span class="hl-number">15</span>:<span class="hl-number">57</span>Z
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: db-secret
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> namespace</span>: default
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> resourceVersion</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"357496"</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> selfLink</span>: /api/v1/namespaces/default/secrets/db-secret
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> uid</span>: <span class="hl-number">63</span>c89263-<span class="hl-number">6099</span>-<span class="hl-number">11e7</span>-b3da-<span class="hl-number">76d</span>6186905a8
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">type</span>: Opaque</pre><p>Note that the data contains Base64-encoded versions of the literal provided by the create command.</p><p>This secret can then be used by your application for example by exporting the secret’s value as environment variables:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: Deployment
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">metadata</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: ${project.artifactId<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spec</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> template</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> spec</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> containers</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - env</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - name</span>: DB_USERNAME
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> valueFrom</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> secretKeyRef</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: db-secret
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> key</span>: username
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - name</span>: DB_PASSWORD
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> valueFrom</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> secretKeyRef</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: db-secret
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> key</span>: password</pre><p>You can select the Secrets to consume in a number of ways:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p class="simpara">By listing the directories where secrets are mapped:
|
||||||
|
<code class="literal">`
|
||||||
|
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets/db-secret,etc/secrets/postgresql
|
||||||
|
</code>`</p><pre class="literallayout">If you have all the secrets mapped to a common root, you can set them like:</pre><pre class="literallayout">```
|
||||||
|
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets
|
||||||
|
```</pre></li><li class="listitem">By setting a named secret:
|
||||||
|
<code class="literal">`
|
||||||
|
-Dspring.cloud.kubernetes.secrets.name=db-secret
|
||||||
|
</code>`</li><li class="listitem">By defining a list of labels:
|
||||||
|
<code class="literal">`
|
||||||
|
-Dspring.cloud.kubernetes.secrets.labels.broker=activemq
|
||||||
|
-Dspring.cloud.kubernetes.secrets.labels.db=postgresql
|
||||||
|
</code>`</li></ol></div><div class="table"><a name="d0e466" href="#d0e466"></a><p class="title"><b>Table 4.2. Properties:</b></p><div class="table-contents"><table class="table" summary="Properties:" style="border-collapse: collapse;border-top: 1px solid ; border-bottom: 1px solid ; border-left: 1px solid ; border-right: 1px solid ; "><colgroup><col class="col_1"><col class="col_2"><col class="col_3"><col class="col_4"></colgroup><thead><tr><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Name</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Type</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Default</th><th style="border-bottom: 1px solid ; " align="left" valign="top">Description</th></tr></thead><tfoot><tr><th style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.enableApi</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>Boolean</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>false</p></th><th style="" align="left" valign="top"><p>Enable/Disable consuming secrets via APIs (examples 2 and 3)</p></th></tr></tfoot><tbody><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.enabled</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Boolean</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>true</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Enable Secrets PropertySource</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.name</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>String</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>${spring.application.name}</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Sets the name of the secret to lookup</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.namespace</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>String</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Client namespace</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Sets the Kubernetes namespace where to lookup</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.labels</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Map</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>null</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Sets the labels used to lookup secrets</p></td></tr><tr><td style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.paths</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>List</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>null</p></td><td style="" align="left" valign="top"><p>Sets the paths where secrets are mounted (example 1)</p></td></tr></tbody></table></div></div><br class="table-break"><p><span class="strong"><strong>Notes:</strong></span>
|
||||||
|
- The property <code class="literal">spring.cloud.kubernetes.secrets.labels</code> behaves as defined by
|
||||||
|
<a class="link" href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding#map-based-binding" target="_top">Map-based binding</a>.
|
||||||
|
- The property <code class="literal">spring.cloud.kubernetes.secrets.paths</code> behaves as defined by
|
||||||
|
<a class="link" href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding#collection-based-binding" target="_top">Collection-based binding</a>.
|
||||||
|
- Access to secrets via API may be restricted for security reasons, the preferred way is to mount secret to the POD.</p><p>Example of application using secrets (though it hasn’t been updated to use the new <code class="literal">spring-cloud-kubernetes</code> project):
|
||||||
|
<a class="link" href="https://github.com/fabric8-quickstarts/spring-boot-camel-config" target="_top">spring-boot-camel-config</a></p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_propertysource_reload" href="#_propertysource_reload"></a>4.3 PropertySource Reload</h2></div></div></div><p>Some applications may need to detect changes on external property sources and update their internal status to reflect the new configuration.
|
||||||
|
The reload feature of Spring Cloud Kubernetes is able to trigger an application reload when a related <code class="literal">ConfigMap</code> or
|
||||||
|
<code class="literal">Secret</code> changes.</p><p>This feature is disabled by default and can be enabled using the configuration property <code class="literal">spring.cloud.kubernetes.reload.enabled=true</code>
|
||||||
|
(eg. in the <span class="strong"><strong>application.properties</strong></span> file).</p><p>The following levels of reload are supported (property <code class="literal">spring.cloud.kubernetes.reload.strategy</code>):
|
||||||
|
- <span class="strong"><strong><code class="literal">refresh</code> (default)</strong></span>: only configuration beans annotated with <code class="literal">@ConfigurationProperties</code> or <code class="literal">@RefreshScope</code> are reloaded.
|
||||||
|
This reload level leverages the refresh feature of Spring Cloud Context.
|
||||||
|
- <span class="strong"><strong><code class="literal">restart_context</code></strong></span>: the whole Spring <span class="emphasis"><em>ApplicationContext</em></span> is gracefully restarted. Beans are recreated with the new configuration.
|
||||||
|
- <span class="strong"><strong><code class="literal">shutdown</code></strong></span>: the Spring <span class="emphasis"><em>ApplicationContext</em></span> is shut down to activate a restart of the container.
|
||||||
|
When using this level, make sure that the lifecycle of all non-daemon threads is bound to the ApplicationContext
|
||||||
|
and that a replication controller or replica set is configured to restart the pod.</p><p>Example:</p><p>Assuming that the reload feature is enabled with default settings (<span class="strong"><strong><code class="literal">refresh</code></strong></span> mode), the following bean will be refreshed when the config map changes:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||||
|
<em><span class="hl-annotation" style="color: gray">@ConfigurationProperties(prefix = "bean")</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfig {
|
||||||
|
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> String message = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"a message that can be changed live"</span>;
|
||||||
|
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// getter and setters</span>
|
||||||
|
|
||||||
|
}</pre><p>A way to see that changes effectively happen is creating another bean that prints the message periodically.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Component</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyBean {
|
||||||
|
|
||||||
|
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MyConfig config;
|
||||||
|
|
||||||
|
<em><span class="hl-annotation" style="color: gray">@Scheduled(fixedDelay = 5000)</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> hello() {
|
||||||
|
System.out.println(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"The message is: "</span> + config.getMessage());
|
||||||
|
}
|
||||||
|
}</pre><p>The message printed by the application can be changed using a <code class="literal">ConfigMap</code> as follows:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: ConfigMap
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">metadata</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: reload-example
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">data</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> application.properties</span>: |-
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> bean.message</span>=Hello World!</pre><p>Any change to the property named <code class="literal">bean.message</code> in the <code class="literal">ConfigMap</code> associated to the pod will be reflected in the
|
||||||
|
output. More generally speaking, changes associated to properties prefixed with the value defined by the <code class="literal">prefix</code>
|
||||||
|
field of the <code class="literal">@ConfigurationProperties</code> annotation will be detected and reflected in the application.
|
||||||
|
[Associating a <code class="literal">ConfigMap</code> to a pod](#configmap-propertysource) is explained above.</p><p>The full example is available in [spring-cloud-kubernetes-reload-example](spring-cloud-kubernetes-examples/kubernetes-reload-example).</p><p>The reload feature supports two operating modes:
|
||||||
|
- <span class="strong"><strong>event (default)</strong></span>: watches for changes in config maps or secrets using the Kubernetes API (web socket).
|
||||||
|
Any event will produce a re-check on the configuration and a reload in case of changes.
|
||||||
|
The <code class="literal">view</code> role on the service account is required in order to listen for config map changes. A higher level role (eg. <code class="literal">edit</code>) is required for secrets
|
||||||
|
(secrets are not monitored by default).
|
||||||
|
- <span class="strong"><strong>polling</strong></span>: re-creates the configuration periodically from config maps and secrets to see if it has changed.
|
||||||
|
The polling period can be configured using the property <code class="literal">spring.cloud.kubernetes.reload.period</code> and defaults to <span class="strong"><strong>15 seconds</strong></span>.
|
||||||
|
It requires the same role as the monitored property source.
|
||||||
|
This means, for example, that using polling on file mounted secret sources does not require particular privileges.</p><div class="table"><a name="d0e696" href="#d0e696"></a><p class="title"><b>Table 4.3. Properties:</b></p><div class="table-contents"><table class="table" summary="Properties:" style="border-collapse: collapse;border-top: 1px solid ; border-bottom: 1px solid ; border-left: 1px solid ; border-right: 1px solid ; "><colgroup><col class="col_1"><col class="col_2"><col class="col_3"><col class="col_4"></colgroup><thead><tr><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Name</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Type</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Default</th><th style="border-bottom: 1px solid ; " align="left" valign="top">Description</th></tr></thead><tfoot><tr><th style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.period</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>Duration</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>15s</p></th><th style="" align="left" valign="top"><p>The period for verifying changes when using the <span class="strong"><strong>polling</strong></span> strategy</p></th></tr></tfoot><tbody><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.enabled</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Boolean</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>false</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Enables monitoring of property sources and configuration reload</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.monitoring-config-maps</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Boolean</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>true</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Allow monitoring changes in config maps</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.monitoring-secrets</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Boolean</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>false</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Allow monitoring changes in secrets</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.strategy</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Enum</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>refresh</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>The strategy to use when firing a reload (<span class="strong"><strong>refresh</strong></span>, <span class="strong"><strong>restart_context</strong></span>, <span class="strong"><strong>shutdown</strong></span>)</p></td></tr><tr><td style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.mode</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>Enum</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>event</p></td><td style="" align="left" valign="top"><p>Specifies how to listen for changes in property sources (<span class="strong"><strong>event</strong></span>, <span class="strong"><strong>polling</strong></span>)</p></td></tr></tbody></table></div></div><br class="table-break"><p><span class="strong"><strong>Notes</strong></span>:
|
||||||
|
- Properties under <span class="strong"><strong>spring.cloud.kubernetes.reload.</strong></span> should not be used in config maps or secrets: changing such properties at runtime may lead to unexpected results;
|
||||||
|
- Deleting a property or the whole config map does not restore the original state of the beans when using the <span class="strong"><strong>refresh</strong></span> level.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__kubernetes_native_service_discovery.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__ribbon_discovery_in_kubernetes.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3. Kubernetes native service discovery </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 5. Ribbon discovery in Kubernetes</td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>8. Leader Election</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__pod_health_indicator.html" title="7. Pod Health Indicator"><link rel="next" href="multi__security_configurations_inside_kubernetes.html" title="9. Security Configurations inside Kubernetes"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">8. Leader Election</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__pod_health_indicator.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__security_configurations_inside_kubernetes.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_leader_election" href="#_leader_election"></a>8. Leader Election</h1></div></div></div><p><TBD></p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__pod_health_indicator.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__security_configurations_inside_kubernetes.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">7. Pod Health Indicator </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 9. Security Configurations inside Kubernetes</td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>11. Other Resources</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__examples.html" title="10. Examples"><link rel="next" href="multi__building.html" title="12. Building"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">11. Other Resources</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__examples.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__building.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_other_resources" href="#_other_resources"></a>11. Other Resources</h1></div></div></div><p>Here you can find other resources such as presentations(slides) and videos about Spring Cloud Kubernetes.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="https://salaboy.com/2018/09/27/the-s1p-experience/" target="_top">S1P Spring Cloud on PKS</a></li><li class="listitem"><a class="link" href="https://salaboy.com/2018/07/18/ljc-july-18-spring-cloud-docker-k8s/" target="_top">Spring Cloud, Docker, Kubernetes → London Java Community July 2018</a></li></ul></div><p>Please feel free to submit other resources via PR to <a class="link" href="http://github.com/spring-cloud/spring-cloud-kubernetes" target="_top">this repository</a>.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__examples.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__building.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">10. Examples </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 12. Building</td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>7. Pod Health Indicator</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__kubernetes_ecosystem_awareness.html" title="6. Kubernetes Ecosystem Awareness"><link rel="next" href="multi__leader_election.html" title="8. Leader Election"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">7. Pod Health Indicator</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__kubernetes_ecosystem_awareness.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__leader_election.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_pod_health_indicator" href="#_pod_health_indicator"></a>7. Pod Health Indicator</h1></div></div></div><p>Spring Boot uses <a class="link" href="https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpoint.java" target="_top">HealthIndicator</a> to expose info about the health of an application.
|
||||||
|
That makes it really useful for exposing health related information to the user and are also a good fit for use as <a class="link" href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/" target="_top">readiness probes</a>.</p><p>The Kubernetes health indicator which is part of the core module exposes the following info:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">pod name, ip address, namespace, service account, node name and its ip address</li><li class="listitem">flag that indicates if the Spring Boot application is internal or external to Kubernetes</li></ul></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__kubernetes_ecosystem_awareness.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__leader_election.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6. Kubernetes Ecosystem Awareness </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 8. Leader Election</td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>5. Ribbon discovery in Kubernetes</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__kubernetes_propertysource_implementations.html" title="4. Kubernetes PropertySource implementations"><link rel="next" href="multi__kubernetes_ecosystem_awareness.html" title="6. Kubernetes Ecosystem Awareness"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5. Ribbon discovery in Kubernetes</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__kubernetes_propertysource_implementations.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__kubernetes_ecosystem_awareness.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_ribbon_discovery_in_kubernetes" href="#_ribbon_discovery_in_kubernetes"></a>5. Ribbon discovery in Kubernetes</h1></div></div></div><p>Spring Cloud client applications calling a microservice should be interested on relying on a client load-balancing
|
||||||
|
feature in order to automatically discover at which endpoint(s) it can reach a given service. This mechanism has been
|
||||||
|
implemented within the [spring-cloud-kubernetes-ribbon](spring-cloud-kubernetes-ribbon/pom.xml) project where a
|
||||||
|
Kubernetes client will populate a <a class="link" href="https://github.com/Netflix/ribbon" target="_top">Ribbon</a> <code class="literal">ServerList</code> containing information
|
||||||
|
about such endpoints.</p><p>The implementation is part of the following starter that you can use by adding its dependency to your pom file:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-kubernetes-ribbon<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${latest.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>When the list of the endpoints is populated, the Kubernetes client will search the registered endpoints living in
|
||||||
|
the current namespace/project matching the service name defined using the Ribbon Client annotation:</p><pre class="programlisting">@RibbonClient(name = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name-service"</span>)</pre><p>You can configure Ribbon’s behavior by providing properties in your <code class="literal">application.properties</code> (via your application’s
|
||||||
|
dedicated <code class="literal">ConfigMap</code>) using the following format: <code class="literal"><name of your service>.ribbon.<Ribbon configuration key></code> where:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal"><name of your service></code> corresponds to the service name you’re accessing over Ribbon, as configured using the
|
||||||
|
<code class="literal">@RibbonClient</code> annotation (e.g. <code class="literal">name-service</code> in the example above)</li><li class="listitem"><code class="literal"><Ribbon configuration key></code> is one of the Ribbon configuration key defined by
|
||||||
|
<a class="link" href="https://github.com/Netflix/ribbon/blob/master/ribbon-core/src/main/java/com/netflix/client/config/CommonClientConfigKey.java" target="_top">Ribbon’s CommonClientConfigKey class</a></li></ul></div><p>Additionally, the <code class="literal">spring-cloud-kubernetes-ribbon</code> project defines two additional configuration keys to further
|
||||||
|
control how Ribbon interacts with Kubernetes. In particular, if an endpoint defines multiple ports, the default
|
||||||
|
behavior is to use the first one found. To select more specifically which port to use, in a multi-port service, use
|
||||||
|
the <code class="literal">PortName</code> key. If you want to specify in which Kubernetes' namespace the target service should be looked up, use
|
||||||
|
the <code class="literal">KubernetesNamespace</code> key, remembering in both instances to prefix these keys with your service name and
|
||||||
|
<code class="literal">ribbon</code> prefix as specified above.</p><p>Examples that are using this module for ribbon discovery are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="./spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example" target="_top">Spring Cloud Circuitbreaker and Ribbon</a></li><li class="listitem"><a class="link" href="https://github.com/fabric8-quickstarts/spring-boot-ribbon" target="_top">fabric8-quickstarts - Spring Boot - Ribbon</a></li><li class="listitem"><a class="link" href="https://github.com/fabric8io/kubeflix/tree/master/examples/loanbroker/bank" target="_top">Kubeflix - LoanBroker - Bank</a></li></ul></div><p><span class="strong"><strong>Note</strong></span>: The Ribbon discovery client can be disabled by setting this key within the application properties file
|
||||||
|
<code class="literal">spring.cloud.kubernetes.ribbon.enabled=false</code>.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__kubernetes_propertysource_implementations.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__kubernetes_ecosystem_awareness.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4. Kubernetes PropertySource implementations </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 6. Kubernetes Ecosystem Awareness</td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>9. Security Configurations inside Kubernetes</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi__leader_election.html" title="8. Leader Election"><link rel="next" href="multi__examples.html" title="10. Examples"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">9. Security Configurations inside Kubernetes</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__leader_election.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__examples.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_security_configurations_inside_kubernetes" href="#_security_configurations_inside_kubernetes"></a>9. Security Configurations inside Kubernetes</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_namespace" href="#_namespace"></a>9.1 Namespace</h2></div></div></div><p>Most of the components provided in this project need to know the namespace. For Kubernetes (1.3+) the namespace is made available to pod as part of the service account secret and automatically detected by the client.
|
||||||
|
For earlier version it needs to be specified as an env var to the pod. A quick way to do this is:</p><pre class="literallayout">env:
|
||||||
|
- name: "KUBERNETES_NAMESPACE"
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: "metadata.namespace"</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_service_account" href="#_service_account"></a>9.2 Service Account</h2></div></div></div><p>For distros of Kubernetes that support more fine-grained role-based access within the cluster, you need to make sure a pod that runs with spring-cloud-kubernetes has access to the Kubernetes API.
|
||||||
|
For any service accounts you assign to a deployment/pod, you need to make sure it has the correct roles. For example, you can add <code class="literal">cluster-reader</code> permissions to your <code class="literal">default</code> service account depending on the project you’re in:</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__leader_election.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__examples.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8. Leader Election </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 10. Examples</td></tr></table></div></body></html>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>1. Why do you need Spring Cloud Kubernetes?</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="up" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="prev" href="multi_spring-cloud-kubernetes.html" title="Spring Cloud Kubernetes"><link rel="next" href="multi__discoveryclient_for_kubernetes.html" title="2. DiscoveryClient for Kubernetes"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">1. Why do you need Spring Cloud Kubernetes?</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-kubernetes.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__discoveryclient_for_kubernetes.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_why_do_you_need_spring_cloud_kubernetes" href="#_why_do_you_need_spring_cloud_kubernetes"></a>1. Why do you need Spring Cloud Kubernetes?</h1></div></div></div><p>Spring Cloud Kubernetes provide Spring Cloud common interfaces implementations to consume Kubernetes native services.
|
||||||
|
The main objective of the projects provided in this repository is to facilitate the integration of Spring Cloud/Spring Boot applications running inside Kubernetes.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-kubernetes.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__discoveryclient_for_kubernetes.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Spring Cloud Kubernetes </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-kubernetes.html">Home</a></td><td width="40%" align="right" valign="top"> 2. DiscoveryClient for Kubernetes</td></tr></table></div></body></html>
|
||||||
35
spring-cloud-kubernetes/1.0.0.RC2/single/css/highlight.css
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
code highlight CSS resemblign the Eclipse IDE default color schema
|
||||||
|
@author Costin Leau
|
||||||
|
*/
|
||||||
|
|
||||||
|
.hl-keyword {
|
||||||
|
color: #7F0055;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-comment {
|
||||||
|
color: #3F5F5F;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-multiline-comment {
|
||||||
|
color: #3F5FBF;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-tag {
|
||||||
|
color: #3F7F7F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-attribute {
|
||||||
|
color: #7F007F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-value {
|
||||||
|
color: #2A00FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-string {
|
||||||
|
color: #2A00FF;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
@IMPORT url("manual.css");
|
||||||
|
|
||||||
|
body.firstpage {
|
||||||
|
background: url("../images/background.png") no-repeat center top;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.part h1 {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@IMPORT url("manual.css");
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: url("../images/background.png") no-repeat center top;
|
||||||
|
}
|
||||||
|
|
||||||
344
spring-cloud-kubernetes/1.0.0.RC2/single/css/manual.css
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
@IMPORT url("highlight.css");
|
||||||
|
|
||||||
|
html {
|
||||||
|
padding: 0pt;
|
||||||
|
margin: 0pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: #333333;
|
||||||
|
margin: 15px 30px;
|
||||||
|
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: Consolas, "Liberation Mono", Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(a)>code {
|
||||||
|
color: #6D180B;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre)>code {
|
||||||
|
background-color: #F2F2F2;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 1px 3px 0;
|
||||||
|
text-shadow: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
body>*:first-child {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin: 0pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
background: #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3,h4,h5,h6 {
|
||||||
|
color: #000000;
|
||||||
|
cursor: text;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 30px 0 10px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3 {
|
||||||
|
margin: 40px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 70px 0 30px;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.part h1 {
|
||||||
|
border-top: 1px dotted #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h1 code {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2,h2 code {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3,h3 code {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,h1 code,h5,h5 code,h6,h6 code {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.book,div.chapter,div.appendix,div.part,div.preface {
|
||||||
|
min-width: 300px;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.releaseinfo {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.authorgroup {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.copyright {
|
||||||
|
line-height: 1;
|
||||||
|
margin-bottom: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legalnotice p {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.titlepage+p,div.titlepage+p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
line-height: 1.0;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #4183C4;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 15px 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,ol {
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table {
|
||||||
|
margin: 1em;
|
||||||
|
padding: 0.5em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table table,div.informaltable table {
|
||||||
|
display: table;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table td {
|
||||||
|
padding-left: 7px;
|
||||||
|
padding-right: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
line-height: 1.4;
|
||||||
|
padding: 0 20px;
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
border-radius: 3px 3px 3px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar p.title {
|
||||||
|
color: #6D180B;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.programlisting,pre.screen {
|
||||||
|
font-size: 15px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
border-radius: 3px 3px 3px 3px;
|
||||||
|
clear: both;
|
||||||
|
overflow: auto;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-family: Consolas, "Liberation Mono", Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
border: 1px solid #DDDDDD !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
border-collapse: separate !important;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
table thead {
|
||||||
|
background: #F5F5F5;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr {
|
||||||
|
border: none;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th,table td {
|
||||||
|
border: none !important;
|
||||||
|
padding: 6px 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr:nth-child(2n) {
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
}
|
||||||
|
|
||||||
|
td p {
|
||||||
|
margin: 0 0 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table-contents td p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
|
||||||
|
{
|
||||||
|
border: none !important;
|
||||||
|
background: none !important;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important p,div.note p,div.tip p,div.warning p {
|
||||||
|
color: #6F6F6F;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important code,div.note code,div.tip code,div.warning code {
|
||||||
|
background-color: #F2F2F2 !important;
|
||||||
|
border: 1px solid #CCCCCC !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
padding: 1px 3px 0 !important;
|
||||||
|
text-shadow: none !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note th,.tip th,.warning th {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
|
||||||
|
{
|
||||||
|
border-right: 1px solid #CCCCCC !important;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.calloutlist p,div.calloutlist td {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.calloutlist>table>tbody>tr>td:first-child {
|
||||||
|
padding-left: 10px;
|
||||||
|
width: 30px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important,div.note,div.tip,div.warning {
|
||||||
|
margin-left: 0px !important;
|
||||||
|
margin-right: 20px !important;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc {
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl,dt {
|
||||||
|
margin-top: 1px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc>dl>dt {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 30px 0 10px 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc>dl>dd>dl>dt {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 20px 0 10px 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toc>dl>dd>dl>dd>dl>dt {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 20px;
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody.footnotes * {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footnote p {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footnote p sup {
|
||||||
|
margin-right: 6px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.navheader {
|
||||||
|
border-bottom: 1px solid #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.navfooter {
|
||||||
|
border-top: 1px solid #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-left: -1em;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title>a {
|
||||||
|
position: absolute;
|
||||||
|
visibility: hidden;
|
||||||
|
display: block;
|
||||||
|
font-size: 0.85em;
|
||||||
|
margin-top: 0.05em;
|
||||||
|
margin-left: -1em;
|
||||||
|
vertical-align: text-top;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title>a:before {
|
||||||
|
content: "\00A7";
|
||||||
|
}
|
||||||
|
|
||||||
|
.title:hover>a,.title>a:hover,.title:hover>a:hover {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title:focus>a,.title>a:focus,.title:focus>a:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
BIN
spring-cloud-kubernetes/1.0.0.RC2/single/images/background.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/single/images/callouts/1.png
Normal file
|
After Width: | Height: | Size: 329 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/single/images/callouts/2.png
Normal file
|
After Width: | Height: | Size: 353 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/single/images/callouts/3.png
Normal file
|
After Width: | Height: | Size: 350 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/single/images/caution.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/single/images/important.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/single/images/logo.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/single/images/note.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
spring-cloud-kubernetes/1.0.0.RC2/single/images/tip.png
Normal file
|
After Width: | Height: | Size: 931 B |
BIN
spring-cloud-kubernetes/1.0.0.RC2/single/images/warning.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,340 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Spring Cloud Kubernetes</title><link rel="stylesheet" type="text/css" href="css/manual-singlepage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div lang="en" class="book"><div class="titlepage"><div><div><h1 class="title"><a name="d0e3"></a>Spring Cloud Kubernetes</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="chapter"><a href="#_why_do_you_need_spring_cloud_kubernetes">1. Why do you need Spring Cloud Kubernetes?</a></span></dt><dt><span class="chapter"><a href="#_discoveryclient_for_kubernetes">2. DiscoveryClient for Kubernetes</a></span></dt><dt><span class="chapter"><a href="#_kubernetes_native_service_discovery">3. Kubernetes native service discovery</a></span></dt><dt><span class="chapter"><a href="#_kubernetes_propertysource_implementations">4. Kubernetes PropertySource implementations</a></span></dt><dd><dl><dt><span class="section"><a href="#_configmap_propertysource">4.1. ConfigMap PropertySource</a></span></dt><dt><span class="section"><a href="#_secrets_propertysource">4.2. Secrets PropertySource</a></span></dt><dt><span class="section"><a href="#_propertysource_reload">4.3. PropertySource Reload</a></span></dt></dl></dd><dt><span class="chapter"><a href="#_ribbon_discovery_in_kubernetes">5. Ribbon discovery in Kubernetes</a></span></dt><dt><span class="chapter"><a href="#_kubernetes_ecosystem_awareness">6. Kubernetes Ecosystem Awareness</a></span></dt><dd><dl><dt><span class="section"><a href="#_kubernetes_profile_autoconfiguration">6.1. Kubernetes Profile Autoconfiguration</a></span></dt><dt><span class="section"><a href="#_istio_awareness">6.2. Istio Awareness</a></span></dt></dl></dd><dt><span class="chapter"><a href="#_pod_health_indicator">7. Pod Health Indicator</a></span></dt><dt><span class="chapter"><a href="#_leader_election">8. Leader Election</a></span></dt><dt><span class="chapter"><a href="#_security_configurations_inside_kubernetes">9. Security Configurations inside Kubernetes</a></span></dt><dd><dl><dt><span class="section"><a href="#_namespace">9.1. Namespace</a></span></dt><dt><span class="section"><a href="#_service_account">9.2. Service Account</a></span></dt></dl></dd><dt><span class="chapter"><a href="#_examples">10. Examples</a></span></dt><dt><span class="chapter"><a href="#_other_resources">11. Other Resources</a></span></dt><dt><span class="chapter"><a href="#_building">12. Building</a></span></dt><dd><dl><dt><span class="section"><a href="#_basic_compile_and_test">12.1. Basic Compile and Test</a></span></dt><dt><span class="section"><a href="#_documentation">12.2. Documentation</a></span></dt><dt><span class="section"><a href="#_working_with_the_code">12.3. Working with the code</a></span></dt><dd><dl><dt><span class="section"><a href="#_importing_into_eclipse_with_m2eclipse">12.3.1. Importing into eclipse with m2eclipse</a></span></dt><dt><span class="section"><a href="#_importing_into_eclipse_without_m2eclipse">12.3.2. Importing into eclipse without m2eclipse</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#_contributing">13. Contributing</a></span></dt><dd><dl><dt><span class="section"><a href="#_sign_the_contributor_license_agreement">13.1. Sign the Contributor License Agreement</a></span></dt><dt><span class="section"><a href="#_code_of_conduct">13.2. Code of Conduct</a></span></dt><dt><span class="section"><a href="#_code_conventions_and_housekeeping">13.3. Code Conventions and Housekeeping</a></span></dt></dl></dd></dl></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_why_do_you_need_spring_cloud_kubernetes" href="#_why_do_you_need_spring_cloud_kubernetes"></a>1. Why do you need Spring Cloud Kubernetes?</h1></div></div></div><p>Spring Cloud Kubernetes provide Spring Cloud common interfaces implementations to consume Kubernetes native services.
|
||||||
|
The main objective of the projects provided in this repository is to facilitate the integration of Spring Cloud/Spring Boot applications running inside Kubernetes.</p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_discoveryclient_for_kubernetes" href="#_discoveryclient_for_kubernetes"></a>2. DiscoveryClient for Kubernetes</h1></div></div></div><p>This project provides an implementation of <a class="link" href="https://github.com/spring-cloud/spring-cloud-commons/blob/master/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/DiscoveryClient.java" target="_top">Discovery Client</a>
|
||||||
|
for <a class="link" href="http://kubernetes.io" target="_top">Kubernetes</a>.
|
||||||
|
This allows you to query Kubernetes endpoints <span class="strong"><strong>(see <a class="link" href="http://kubernetes.io/docs/user-guide/services/" target="_top">services</a>)</strong></span> by name.
|
||||||
|
A service is typically exposed by the Kubernetes API server as a collection of endpoints which represent <code class="literal">http</code>, <code class="literal">https</code> addresses that a client can
|
||||||
|
access from a Spring Boot application running as a pod. This discovery feature is also used by the Spring Cloud Kubernetes Ribbon project
|
||||||
|
to fetch the list of the endpoints defined for an application to be load balanced.</p><p>This is something that you get for free just by adding the following dependency inside your project:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-kubernetes<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${latest.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>To enable loading of the <code class="literal">DiscoveryClient</code>, add <code class="literal">@EnableDiscoveryClient</code> to the according configuration or application class like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
|
||||||
|
<em><span class="hl-annotation" style="color: gray">@EnableDiscoveryClient</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> main(String[] args) {
|
||||||
|
SpringApplication.run(Application.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, args);
|
||||||
|
}
|
||||||
|
}</pre><p>Then you can inject the client in your code simply by:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> DiscoveryClient discoveryClient;</pre><p>If for any reason you need to disable the <code class="literal">DiscoveryClient</code> you can simply set the following property in <code class="literal">application.properties</code>:</p><pre class="screen">spring.cloud.kubernetes.discovery.enabled=false</pre><p>Some Spring Cloud components use the <code class="literal">DiscoveryClient</code> in order to obtain info about the local service instance. For
|
||||||
|
this to work you need to align the Kubernetes service name with the <code class="literal">spring.application.name</code> property.</p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_kubernetes_native_service_discovery" href="#_kubernetes_native_service_discovery"></a>3. Kubernetes native service discovery</h1></div></div></div><p>Kubernetes itself is capable of (server side) service discovery (see: <a class="link" href="https://kubernetes.io/docs/concepts/services-networking/service/#discovering-services" target="_top">https://kubernetes.io/docs/concepts/services-networking/service/#discovering-services</a>).
|
||||||
|
Using native kubernetes service discovery ensures compatibility with additional tooling, like: istio <a class="link" href="https://istio.io" target="_top">https://istio.io</a> (service mesh, capable of load balancing, ribbon, circuit breaker, failover and much more).</p><p>The caller service just needs to refer to names resolvable in particular kubernetes cluster then. Simplest implementation might use the spring <code class="literal">RestTemplate</code> referring to fully qualified domain name (FQDN) <code class="literal"><a class="link" href="http://{service-name}.{namespace}.svc.{cluster}.local:{service-port}" target="_top">http://{service-name}.{namespace}.svc.{cluster}.local:{service-port}</a></code>.</p><p>Additionally, hystrix can be used for:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">circuit breaker implementation on the caller side, just by annotating the spring boot application class: <code class="literal">@EnableCircuitBreaker</code></li><li class="listitem">and for the fallback functionality, annotating the respective method via: <code class="literal">@HystrixCommand(fallbackMethod=</code> does the job.</li></ul></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_kubernetes_propertysource_implementations" href="#_kubernetes_propertysource_implementations"></a>4. Kubernetes PropertySource implementations</h1></div></div></div><p>The most common approach to configure your Spring Boot application is to create an <code class="literal">application.properties|yaml</code> or
|
||||||
|
an <code class="literal">application-profile.properties|yaml</code> file containing key-value pairs providing customization values to your
|
||||||
|
application or Spring Boot starters. Users may override these properties by specifying system properties or environment
|
||||||
|
variables.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_configmap_propertysource" href="#_configmap_propertysource"></a>4.1 ConfigMap PropertySource</h2></div></div></div><p>Kubernetes provides a resource named <a class="link" href="http://kubernetes.io/docs/user-guide/configmap/" target="_top">ConfigMap</a> to externalize the
|
||||||
|
parameters to pass to your application in the form of key-value pairs or embedded <code class="literal">application.properties|yaml</code> files.
|
||||||
|
The <a class="link" href="./spring-cloud-kubernetes-config" target="_top">Spring Cloud Kubernetes Config</a> project makes Kubernetes `ConfigMap`s available
|
||||||
|
during application bootstrapping and triggers hot reloading of beans or Spring context when changes are detected on
|
||||||
|
observed `ConfigMap`s.</p><p>The default behavior is to create a <code class="literal">ConfigMapPropertySource</code> based on a Kubernetes <code class="literal">ConfigMap</code> which has <code class="literal">metadata.name</code> of either the name of
|
||||||
|
your Spring application (as defined by its <code class="literal">spring.application.name</code> property) or a custom name defined within the
|
||||||
|
<code class="literal">bootstrap.properties</code> file under the following key <code class="literal">spring.cloud.kubernetes.config.name</code>.</p><p>However, more advanced configuration are possible where multiple ConfigMaps can be used
|
||||||
|
This is made possible by the <code class="literal">spring.cloud.kubernetes.config.sources</code> list.
|
||||||
|
For example one could define the following ConfigMaps</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> application</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: cloud-k8s-app
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> cloud</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> kubernetes</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> config</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: default-name
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> namespace</span>: default-namespace
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> sources</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Spring Cloud Kubernetes will lookup a ConfigMap named c1 in namespace default-namespace</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - name</span>: c1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Spring Cloud Kubernetes will lookup a ConfigMap named default-name in whatever namespace n2</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - namespace</span>: n2
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"># Spring Cloud Kubernetes will lookup a ConfigMap named c3 in namespace n3</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - namespace</span>: n3
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: c3</pre><p>In the example above, it <code class="literal">spring.cloud.kubernetes.config.namespace</code> had not been set,
|
||||||
|
then the ConfigMap named <code class="literal">c1</code> would be looked up in the namespace that the application runs</p><p>Any matching <code class="literal">ConfigMap</code> that is found, will be processed as follows:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">apply individual configuration properties.</li><li class="listitem">apply as <code class="literal">yaml</code> the content of any property named <code class="literal">application.yaml</code></li><li class="listitem">apply as properties file the content of any property named <code class="literal">application.properties</code></li></ul></div><p>The single exception to the aforementioned flow is when the <code class="literal">ConfigMap</code> contains a <span class="strong"><strong>single</strong></span> key that indicates
|
||||||
|
the file is a YAML or Properties file. In that case the name of the key does NOT have to be <code class="literal">application.yaml</code> or
|
||||||
|
<code class="literal">application.properties</code> (it can be anything) and the value of the property will be treated correctly.
|
||||||
|
This features facilitates the use case where the <code class="literal">ConfigMap</code> was created using something like:</p><p><code class="literal">kubectl create configmap game-config --from-file=/path/to/app-config.yaml</code></p><p>Example:</p><p>Let’s assume that we have a Spring Boot application named <code class="literal">demo</code> that uses properties to read its thread pool
|
||||||
|
configuration.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">pool.size.core</code></li><li class="listitem"><code class="literal">pool.size.maximum</code></li></ul></div><p>This can be externalized to config map in <code class="literal">yaml</code> format:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: ConfigMap
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">metadata</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: demo
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">data</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> pool.size.core</span>: <span class="hl-number">1</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> pool.size.max</span>: <span class="hl-number">16</span></pre><p>Individual properties work fine for most cases but sometimes embedded <code class="literal">yaml</code> is more convenient. In this case we will
|
||||||
|
use a single property named <code class="literal">application.yaml</code> to embed our <code class="literal">yaml</code>:</p><pre class="literallayout"> ```yaml
|
||||||
|
kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: demo
|
||||||
|
data:
|
||||||
|
application.yaml: |-
|
||||||
|
pool:
|
||||||
|
size:
|
||||||
|
core: 1
|
||||||
|
max:16</pre><pre class="screen">The following also works:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: demo
|
||||||
|
data:
|
||||||
|
custom-name.yaml: |-
|
||||||
|
pool:
|
||||||
|
size:
|
||||||
|
core: 1
|
||||||
|
max:16</pre><p>Spring Boot applications can also be configured differently depending on active profiles which will be merged together
|
||||||
|
when the ConfigMap is read. It is possible to provide different property values for different profiles using an
|
||||||
|
<code class="literal">application.properties|yaml</code> property, specifying profile-specific values each in their own document
|
||||||
|
(indicated by the <code class="literal">---</code> sequence) as follows:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: ConfigMap
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">metadata</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: demo
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">data</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> application.yml</span>: |-
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> greeting</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Hello to the World
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> farewell</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Goodbye
|
||||||
|
---
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> spring</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> profiles</span>: development
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> greeting</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Hello to the Developers
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> farewell</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Goodbye to the Developers
|
||||||
|
---
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> spring</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> profiles</span>: production
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> greeting</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Hello to the Ops</pre><p>In the above case, the configuration loaded into your Spring Application with the <code class="literal">development</code> profile will be:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> greeting</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Hello to the Developers
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> farewell</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Goodbye to the Developers</pre><p>whereas if the <code class="literal">production</code> profile is active, the configuration will be:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> greeting</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Hello to the Ops
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> farewell</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> message</span>: Say Goodbye</pre><p>If both profiles are active, the property which appears last within the configmap will overwrite preceding values.</p><p>To tell to Spring Boot which <code class="literal">profile</code> should be enabled at bootstrap, a system property can be passed to the Java
|
||||||
|
command launching your Spring Boot application using an env variable that you will define with the OpenShift
|
||||||
|
<code class="literal">DeploymentConfig</code> or Kubernetes <code class="literal">ReplicationConfig</code> resource file as follows:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: DeploymentConfig
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spec</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> replicas</span>: <span class="hl-number">1</span>
|
||||||
|
...
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> spec</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> containers</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - env</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - name</span>: JAVA_APP_DIR
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> value</span>: /deployments
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - name</span>: JAVA_OPTIONS
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> value</span>: -Dspring.profiles.active=developer</pre><p><span class="strong"><strong>Notes:</strong></span>
|
||||||
|
- check the security configuration section, to access config maps from inside a pod you need to have the correct
|
||||||
|
Kubernetes service accounts, roles and role bindings.</p><p>Another option for using ConfigMaps, is to mount them into the Pod running the Spring Cloud Kubernetes application
|
||||||
|
and have Spring Cloud Kubernetes read them from the file system.
|
||||||
|
This behavior is controlled by the <code class="literal">spring.cloud.kubernetes.config.paths</code> property and can be used in
|
||||||
|
addition to or instead of the mechanism described earlier.
|
||||||
|
Multiple (exact) file paths can be specified in <code class="literal">spring.cloud.kubernetes.config.paths</code> by using the <code class="literal">,</code> delimiter</p><div class="table"><a name="d0e301" href="#d0e301"></a><p class="title"><b>Table 4.1. Properties:</b></p><div class="table-contents"><table class="table" summary="Properties:" style="border-collapse: collapse;border-top: 1px solid ; border-bottom: 1px solid ; border-left: 1px solid ; border-right: 1px solid ; "><colgroup><col class="col_1"><col class="col_2"><col class="col_3"><col class="col_4"></colgroup><thead><tr><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Name</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Type</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Default</th><th style="border-bottom: 1px solid ; " align="left" valign="top">Description</th></tr></thead><tfoot><tr><th style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.config.enableApi</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>Boolean</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>true</p></th><th style="" align="left" valign="top"><p>Enable/Disable consuming ConfigMaps via APIs</p></th></tr></tfoot><tbody><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.config.enabled</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Boolean</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>true</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Enable Secrets PropertySource</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.config.name</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>String</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>${spring.application.name}</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Sets the name of ConfigMap to lookup</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.config.namespace</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>String</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Client namespace</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Sets the Kubernetes namespace where to lookup</p></td></tr><tr><td style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.config.paths</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>List</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>null</p></td><td style="" align="left" valign="top"><p>Sets the paths where ConfigMaps are mounted</p></td></tr></tbody></table></div></div><br class="table-break"></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_secrets_propertysource" href="#_secrets_propertysource"></a>4.2 Secrets PropertySource</h2></div></div></div><p>Kubernetes has the notion of [Secrets](<a class="link" href="https://kubernetes.io/docs/concepts/configuration/secret/" target="_top">https://kubernetes.io/docs/concepts/configuration/secret/</a>) for storing
|
||||||
|
sensitive data such as password, OAuth tokens, etc. This project provides integration with <code class="literal">Secrets</code> to make secrets
|
||||||
|
accessible by Spring Boot applications. This feature can be explicitly enabled/disabled using the <code class="literal">spring.cloud.kubernetes.secrets.enabled</code> property.</p><p>The <code class="literal">SecretsPropertySource</code> when enabled will lookup Kubernetes for <code class="literal">Secrets</code> from the following sources:
|
||||||
|
1. reading recursively from secrets mounts
|
||||||
|
2. named after the application (as defined by <code class="literal">spring.application.name</code>)
|
||||||
|
3. matching some labels</p><p>Please note that by default, consuming Secrets via API (points 2 and 3 above) <span class="strong"><strong>is not enabled</strong></span> for security reasons
|
||||||
|
and it is recommend that containers share secrets via mounted volumes. Otherwise proper RBAC security configurations must be provided
|
||||||
|
to make sure that unauthorized access to Secrets occurs.</p><p>If the secrets are found their data is made available to the application.</p><p><span class="strong"><strong>Example:</strong></span></p><p>Let’s assume that we have a spring boot application named <code class="literal">demo</code> that uses properties to read its database
|
||||||
|
configuration. We can create a Kubernetes secret using the following command:</p><pre class="screen">oc create secret generic db-secret --from-literal=username=user --from-literal=password=p455w0rd</pre><p>This would create the following secret (shown using <code class="literal">oc get secrets db-secret -o yaml</code>):</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">data</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> password</span>: cDQ1NXcwcmQ=
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> username</span>: dXNlcg==
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: Secret
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">metadata</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> creationTimestamp</span>: <span class="hl-number">2017</span>-<span class="hl-number">07</span>-<span class="hl-number">04</span>T09:<span class="hl-number">15</span>:<span class="hl-number">57</span>Z
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: db-secret
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> namespace</span>: default
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> resourceVersion</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"357496"</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> selfLink</span>: /api/v1/namespaces/default/secrets/db-secret
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> uid</span>: <span class="hl-number">63</span>c89263-<span class="hl-number">6099</span>-<span class="hl-number">11e7</span>-b3da-<span class="hl-number">76d</span>6186905a8
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">type</span>: Opaque</pre><p>Note that the data contains Base64-encoded versions of the literal provided by the create command.</p><p>This secret can then be used by your application for example by exporting the secret’s value as environment variables:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: Deployment
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">metadata</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: ${project.artifactId<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spec</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> template</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> spec</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> containers</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - env</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - name</span>: DB_USERNAME
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> valueFrom</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> secretKeyRef</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: db-secret
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> key</span>: username
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> - name</span>: DB_PASSWORD
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> valueFrom</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> secretKeyRef</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: db-secret
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> key</span>: password</pre><p>You can select the Secrets to consume in a number of ways:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p class="simpara">By listing the directories where secrets are mapped:
|
||||||
|
<code class="literal">`
|
||||||
|
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets/db-secret,etc/secrets/postgresql
|
||||||
|
</code>`</p><pre class="literallayout">If you have all the secrets mapped to a common root, you can set them like:</pre><pre class="literallayout">```
|
||||||
|
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets
|
||||||
|
```</pre></li><li class="listitem">By setting a named secret:
|
||||||
|
<code class="literal">`
|
||||||
|
-Dspring.cloud.kubernetes.secrets.name=db-secret
|
||||||
|
</code>`</li><li class="listitem">By defining a list of labels:
|
||||||
|
<code class="literal">`
|
||||||
|
-Dspring.cloud.kubernetes.secrets.labels.broker=activemq
|
||||||
|
-Dspring.cloud.kubernetes.secrets.labels.db=postgresql
|
||||||
|
</code>`</li></ol></div><div class="table"><a name="d0e466" href="#d0e466"></a><p class="title"><b>Table 4.2. Properties:</b></p><div class="table-contents"><table class="table" summary="Properties:" style="border-collapse: collapse;border-top: 1px solid ; border-bottom: 1px solid ; border-left: 1px solid ; border-right: 1px solid ; "><colgroup><col class="col_1"><col class="col_2"><col class="col_3"><col class="col_4"></colgroup><thead><tr><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Name</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Type</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Default</th><th style="border-bottom: 1px solid ; " align="left" valign="top">Description</th></tr></thead><tfoot><tr><th style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.enableApi</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>Boolean</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>false</p></th><th style="" align="left" valign="top"><p>Enable/Disable consuming secrets via APIs (examples 2 and 3)</p></th></tr></tfoot><tbody><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.enabled</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Boolean</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>true</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Enable Secrets PropertySource</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.name</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>String</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>${spring.application.name}</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Sets the name of the secret to lookup</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.namespace</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>String</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Client namespace</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Sets the Kubernetes namespace where to lookup</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.labels</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Map</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>null</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Sets the labels used to lookup secrets</p></td></tr><tr><td style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.secrets.paths</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>List</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>null</p></td><td style="" align="left" valign="top"><p>Sets the paths where secrets are mounted (example 1)</p></td></tr></tbody></table></div></div><br class="table-break"><p><span class="strong"><strong>Notes:</strong></span>
|
||||||
|
- The property <code class="literal">spring.cloud.kubernetes.secrets.labels</code> behaves as defined by
|
||||||
|
<a class="link" href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding#map-based-binding" target="_top">Map-based binding</a>.
|
||||||
|
- The property <code class="literal">spring.cloud.kubernetes.secrets.paths</code> behaves as defined by
|
||||||
|
<a class="link" href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding#collection-based-binding" target="_top">Collection-based binding</a>.
|
||||||
|
- Access to secrets via API may be restricted for security reasons, the preferred way is to mount secret to the POD.</p><p>Example of application using secrets (though it hasn’t been updated to use the new <code class="literal">spring-cloud-kubernetes</code> project):
|
||||||
|
<a class="link" href="https://github.com/fabric8-quickstarts/spring-boot-camel-config" target="_top">spring-boot-camel-config</a></p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_propertysource_reload" href="#_propertysource_reload"></a>4.3 PropertySource Reload</h2></div></div></div><p>Some applications may need to detect changes on external property sources and update their internal status to reflect the new configuration.
|
||||||
|
The reload feature of Spring Cloud Kubernetes is able to trigger an application reload when a related <code class="literal">ConfigMap</code> or
|
||||||
|
<code class="literal">Secret</code> changes.</p><p>This feature is disabled by default and can be enabled using the configuration property <code class="literal">spring.cloud.kubernetes.reload.enabled=true</code>
|
||||||
|
(eg. in the <span class="strong"><strong>application.properties</strong></span> file).</p><p>The following levels of reload are supported (property <code class="literal">spring.cloud.kubernetes.reload.strategy</code>):
|
||||||
|
- <span class="strong"><strong><code class="literal">refresh</code> (default)</strong></span>: only configuration beans annotated with <code class="literal">@ConfigurationProperties</code> or <code class="literal">@RefreshScope</code> are reloaded.
|
||||||
|
This reload level leverages the refresh feature of Spring Cloud Context.
|
||||||
|
- <span class="strong"><strong><code class="literal">restart_context</code></strong></span>: the whole Spring <span class="emphasis"><em>ApplicationContext</em></span> is gracefully restarted. Beans are recreated with the new configuration.
|
||||||
|
- <span class="strong"><strong><code class="literal">shutdown</code></strong></span>: the Spring <span class="emphasis"><em>ApplicationContext</em></span> is shut down to activate a restart of the container.
|
||||||
|
When using this level, make sure that the lifecycle of all non-daemon threads is bound to the ApplicationContext
|
||||||
|
and that a replication controller or replica set is configured to restart the pod.</p><p>Example:</p><p>Assuming that the reload feature is enabled with default settings (<span class="strong"><strong><code class="literal">refresh</code></strong></span> mode), the following bean will be refreshed when the config map changes:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||||
|
<em><span class="hl-annotation" style="color: gray">@ConfigurationProperties(prefix = "bean")</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfig {
|
||||||
|
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> String message = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"a message that can be changed live"</span>;
|
||||||
|
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// getter and setters</span>
|
||||||
|
|
||||||
|
}</pre><p>A way to see that changes effectively happen is creating another bean that prints the message periodically.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Component</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyBean {
|
||||||
|
|
||||||
|
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MyConfig config;
|
||||||
|
|
||||||
|
<em><span class="hl-annotation" style="color: gray">@Scheduled(fixedDelay = 5000)</span></em>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> hello() {
|
||||||
|
System.out.println(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"The message is: "</span> + config.getMessage());
|
||||||
|
}
|
||||||
|
}</pre><p>The message printed by the application can be changed using a <code class="literal">ConfigMap</code> as follows:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">apiVersion</span>: v1
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">kind</span>: ConfigMap
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">metadata</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: reload-example
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">data</span>:
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> application.properties</span>: |-
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> bean.message</span>=Hello World!</pre><p>Any change to the property named <code class="literal">bean.message</code> in the <code class="literal">ConfigMap</code> associated to the pod will be reflected in the
|
||||||
|
output. More generally speaking, changes associated to properties prefixed with the value defined by the <code class="literal">prefix</code>
|
||||||
|
field of the <code class="literal">@ConfigurationProperties</code> annotation will be detected and reflected in the application.
|
||||||
|
[Associating a <code class="literal">ConfigMap</code> to a pod](#configmap-propertysource) is explained above.</p><p>The full example is available in [spring-cloud-kubernetes-reload-example](spring-cloud-kubernetes-examples/kubernetes-reload-example).</p><p>The reload feature supports two operating modes:
|
||||||
|
- <span class="strong"><strong>event (default)</strong></span>: watches for changes in config maps or secrets using the Kubernetes API (web socket).
|
||||||
|
Any event will produce a re-check on the configuration and a reload in case of changes.
|
||||||
|
The <code class="literal">view</code> role on the service account is required in order to listen for config map changes. A higher level role (eg. <code class="literal">edit</code>) is required for secrets
|
||||||
|
(secrets are not monitored by default).
|
||||||
|
- <span class="strong"><strong>polling</strong></span>: re-creates the configuration periodically from config maps and secrets to see if it has changed.
|
||||||
|
The polling period can be configured using the property <code class="literal">spring.cloud.kubernetes.reload.period</code> and defaults to <span class="strong"><strong>15 seconds</strong></span>.
|
||||||
|
It requires the same role as the monitored property source.
|
||||||
|
This means, for example, that using polling on file mounted secret sources does not require particular privileges.</p><div class="table"><a name="d0e696" href="#d0e696"></a><p class="title"><b>Table 4.3. Properties:</b></p><div class="table-contents"><table class="table" summary="Properties:" style="border-collapse: collapse;border-top: 1px solid ; border-bottom: 1px solid ; border-left: 1px solid ; border-right: 1px solid ; "><colgroup><col class="col_1"><col class="col_2"><col class="col_3"><col class="col_4"></colgroup><thead><tr><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Name</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Type</th><th style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top">Default</th><th style="border-bottom: 1px solid ; " align="left" valign="top">Description</th></tr></thead><tfoot><tr><th style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.period</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>Duration</p></th><th style="border-right: 1px solid ; " align="left" valign="top"><p>15s</p></th><th style="" align="left" valign="top"><p>The period for verifying changes when using the <span class="strong"><strong>polling</strong></span> strategy</p></th></tr></tfoot><tbody><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.enabled</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Boolean</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>false</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Enables monitoring of property sources and configuration reload</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.monitoring-config-maps</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Boolean</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>true</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Allow monitoring changes in config maps</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.monitoring-secrets</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Boolean</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>false</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>Allow monitoring changes in secrets</p></td></tr><tr><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.strategy</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>Enum</p></td><td style="border-right: 1px solid ; border-bottom: 1px solid ; " align="left" valign="top"><p>refresh</p></td><td style="border-bottom: 1px solid ; " align="left" valign="top"><p>The strategy to use when firing a reload (<span class="strong"><strong>refresh</strong></span>, <span class="strong"><strong>restart_context</strong></span>, <span class="strong"><strong>shutdown</strong></span>)</p></td></tr><tr><td style="border-right: 1px solid ; " align="left" valign="top"><p>spring.cloud.kubernetes.reload.mode</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>Enum</p></td><td style="border-right: 1px solid ; " align="left" valign="top"><p>event</p></td><td style="" align="left" valign="top"><p>Specifies how to listen for changes in property sources (<span class="strong"><strong>event</strong></span>, <span class="strong"><strong>polling</strong></span>)</p></td></tr></tbody></table></div></div><br class="table-break"><p><span class="strong"><strong>Notes</strong></span>:
|
||||||
|
- Properties under <span class="strong"><strong>spring.cloud.kubernetes.reload.</strong></span> should not be used in config maps or secrets: changing such properties at runtime may lead to unexpected results;
|
||||||
|
- Deleting a property or the whole config map does not restore the original state of the beans when using the <span class="strong"><strong>refresh</strong></span> level.</p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_ribbon_discovery_in_kubernetes" href="#_ribbon_discovery_in_kubernetes"></a>5. Ribbon discovery in Kubernetes</h1></div></div></div><p>Spring Cloud client applications calling a microservice should be interested on relying on a client load-balancing
|
||||||
|
feature in order to automatically discover at which endpoint(s) it can reach a given service. This mechanism has been
|
||||||
|
implemented within the [spring-cloud-kubernetes-ribbon](spring-cloud-kubernetes-ribbon/pom.xml) project where a
|
||||||
|
Kubernetes client will populate a <a class="link" href="https://github.com/Netflix/ribbon" target="_top">Ribbon</a> <code class="literal">ServerList</code> containing information
|
||||||
|
about such endpoints.</p><p>The implementation is part of the following starter that you can use by adding its dependency to your pom file:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-kubernetes-ribbon<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${latest.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||||
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>When the list of the endpoints is populated, the Kubernetes client will search the registered endpoints living in
|
||||||
|
the current namespace/project matching the service name defined using the Ribbon Client annotation:</p><pre class="programlisting">@RibbonClient(name = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name-service"</span>)</pre><p>You can configure Ribbon’s behavior by providing properties in your <code class="literal">application.properties</code> (via your application’s
|
||||||
|
dedicated <code class="literal">ConfigMap</code>) using the following format: <code class="literal"><name of your service>.ribbon.<Ribbon configuration key></code> where:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal"><name of your service></code> corresponds to the service name you’re accessing over Ribbon, as configured using the
|
||||||
|
<code class="literal">@RibbonClient</code> annotation (e.g. <code class="literal">name-service</code> in the example above)</li><li class="listitem"><code class="literal"><Ribbon configuration key></code> is one of the Ribbon configuration key defined by
|
||||||
|
<a class="link" href="https://github.com/Netflix/ribbon/blob/master/ribbon-core/src/main/java/com/netflix/client/config/CommonClientConfigKey.java" target="_top">Ribbon’s CommonClientConfigKey class</a></li></ul></div><p>Additionally, the <code class="literal">spring-cloud-kubernetes-ribbon</code> project defines two additional configuration keys to further
|
||||||
|
control how Ribbon interacts with Kubernetes. In particular, if an endpoint defines multiple ports, the default
|
||||||
|
behavior is to use the first one found. To select more specifically which port to use, in a multi-port service, use
|
||||||
|
the <code class="literal">PortName</code> key. If you want to specify in which Kubernetes' namespace the target service should be looked up, use
|
||||||
|
the <code class="literal">KubernetesNamespace</code> key, remembering in both instances to prefix these keys with your service name and
|
||||||
|
<code class="literal">ribbon</code> prefix as specified above.</p><p>Examples that are using this module for ribbon discovery are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="./spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example" target="_top">Spring Cloud Circuitbreaker and Ribbon</a></li><li class="listitem"><a class="link" href="https://github.com/fabric8-quickstarts/spring-boot-ribbon" target="_top">fabric8-quickstarts - Spring Boot - Ribbon</a></li><li class="listitem"><a class="link" href="https://github.com/fabric8io/kubeflix/tree/master/examples/loanbroker/bank" target="_top">Kubeflix - LoanBroker - Bank</a></li></ul></div><p><span class="strong"><strong>Note</strong></span>: The Ribbon discovery client can be disabled by setting this key within the application properties file
|
||||||
|
<code class="literal">spring.cloud.kubernetes.ribbon.enabled=false</code>.</p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_kubernetes_ecosystem_awareness" href="#_kubernetes_ecosystem_awareness"></a>6. Kubernetes Ecosystem Awareness</h1></div></div></div><p>All of the features described above will work equally well regardless of whether your application is running inside
|
||||||
|
Kubernetes or not. This is really helpful for development and troubleshooting.
|
||||||
|
From a development point of view, this is really helpful as you can start your Spring Boot application and debug one
|
||||||
|
of the modules part of this project. It is not required to deploy it in Kubernetes
|
||||||
|
as the code of the project relies on the
|
||||||
|
<a class="link" href="https://github.com/fabric8io/kubernetes-client" target="_top">Fabric8 Kubernetes Java client</a> which is a fluent DSL able to
|
||||||
|
communicate using <code class="literal">http</code> protocol to the REST API of Kubernetes Server.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_kubernetes_profile_autoconfiguration" href="#_kubernetes_profile_autoconfiguration"></a>6.1 Kubernetes Profile Autoconfiguration</h2></div></div></div><p>When the application runs as a pod inside Kubernetes a Spring profile named <code class="literal">kubernetes</code> will automatically get activated.
|
||||||
|
This allows the developer to customize the configuration, to define beans that will be applied when the Spring Boot application is deployed
|
||||||
|
within the Kubernetes platform <span class="strong"><strong>(e.g. different dev and prod configuration)</strong></span>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_istio_awareness" href="#_istio_awareness"></a>6.2 Istio Awareness</h2></div></div></div><p>When including the <span class="strong"><strong>spring-cloud-kubernetes-istio</strong></span> module into the application classpath a new profile will be added to the application,
|
||||||
|
if the application is running inside a Kubernetes Cluster with <a class="link" href="http://istio.io" target="_top">Istio</a> installed. Then you can use
|
||||||
|
spring <span class="strong"><strong>@Profile("istio")</strong></span> annotations into your Beans and <span class="strong"><strong>@Configuration</strong></span>'s.</p><p>The Istio awareness module uses the <span class="strong"><strong>me.snowdrop:istio-client</strong></span> to interact with Istio APIs enabling us to discover traffic rules, circuit breakers, etc.
|
||||||
|
Making it easy for our Spring Boot applications to consume this data to dynamically configure themselves according the environment.</p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_pod_health_indicator" href="#_pod_health_indicator"></a>7. Pod Health Indicator</h1></div></div></div><p>Spring Boot uses <a class="link" href="https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpoint.java" target="_top">HealthIndicator</a> to expose info about the health of an application.
|
||||||
|
That makes it really useful for exposing health related information to the user and are also a good fit for use as <a class="link" href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/" target="_top">readiness probes</a>.</p><p>The Kubernetes health indicator which is part of the core module exposes the following info:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">pod name, ip address, namespace, service account, node name and its ip address</li><li class="listitem">flag that indicates if the Spring Boot application is internal or external to Kubernetes</li></ul></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_leader_election" href="#_leader_election"></a>8. Leader Election</h1></div></div></div><p><TBD></p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_security_configurations_inside_kubernetes" href="#_security_configurations_inside_kubernetes"></a>9. Security Configurations inside Kubernetes</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_namespace" href="#_namespace"></a>9.1 Namespace</h2></div></div></div><p>Most of the components provided in this project need to know the namespace. For Kubernetes (1.3+) the namespace is made available to pod as part of the service account secret and automatically detected by the client.
|
||||||
|
For earlier version it needs to be specified as an env var to the pod. A quick way to do this is:</p><pre class="literallayout">env:
|
||||||
|
- name: "KUBERNETES_NAMESPACE"
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: "metadata.namespace"</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_service_account" href="#_service_account"></a>9.2 Service Account</h2></div></div></div><p>For distros of Kubernetes that support more fine-grained role-based access within the cluster, you need to make sure a pod that runs with spring-cloud-kubernetes has access to the Kubernetes API.
|
||||||
|
For any service accounts you assign to a deployment/pod, you need to make sure it has the correct roles. For example, you can add <code class="literal">cluster-reader</code> permissions to your <code class="literal">default</code> service account depending on the project you’re in:</p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_examples" href="#_examples"></a>10. Examples</h1></div></div></div><p>Spring Cloud Kubernetes tries to make it transparent for your applications to consume Kubernetes Native Services
|
||||||
|
following the Spring Cloud interfaces.</p><p>In your applications, you need to add the <span class="strong"><strong>spring-cloud-kubernetes-discovery</strong></span> dependency to your classpath and remove any other dependency that contains a <span class="strong"><strong>DiscoveryClient</strong></span> implementation (ie. Eureka Discovery Client).
|
||||||
|
The same applies for PropertySourceLocator, where you need to add to the classpath the <span class="strong"><strong>spring-cloud-kubernetes-config</strong></span> and remove any other dependency that contains a <span class="strong"><strong>PropertySourceLocator</strong></span> implementation (ie. Config Server Client).</p><p>The following projects highlight the usage of these dependencies and demonstrate how these libraries can be used from any Spring Boot application.</p><p>List of examples using these projects:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="https://github.com/spring-cloud/spring-cloud-kubernetes/tree/master/spring-cloud-kubernetes-examples" target="_top">Spring Cloud Kubernetes Examples</a>: the ones located inside this repository.</li><li class="listitem">Spring Cloud Kubernetes Full Example: Minions and Boss</li><li class="listitem"><a class="link" href="https://github.com/salaboy/spring-cloud-k8s-minion" target="_top">Minion</a></li><li class="listitem"><a class="link" href="https://github.com/salaboy/spring-cloud-k8s-boss" target="_top">Boss</a></li><li class="listitem">Spring Cloud Kubernetes Full Example: <a class="link" href="https://github.com/salaboy/s1p_docs" target="_top">SpringOne Platform Tickets Service</a></li><li class="listitem"><a class="link" href="https://github.com/salaboy/s1p_gateway" target="_top">Spring Cloud Gateway with Spring Cloud Kubernetes Discovery and Config</a></li><li class="listitem"><a class="link" href="https://github.com/salaboy/showcase-admin-tool" target="_top">Spring Boot Admin with Spring Cloud Kubernetes Discovery and Config</a></li></ul></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_other_resources" href="#_other_resources"></a>11. Other Resources</h1></div></div></div><p>Here you can find other resources such as presentations(slides) and videos about Spring Cloud Kubernetes.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="https://salaboy.com/2018/09/27/the-s1p-experience/" target="_top">S1P Spring Cloud on PKS</a></li><li class="listitem"><a class="link" href="https://salaboy.com/2018/07/18/ljc-july-18-spring-cloud-docker-k8s/" target="_top">Spring Cloud, Docker, Kubernetes → London Java Community July 2018</a></li></ul></div><p>Please feel free to submit other resources via PR to <a class="link" href="http://github.com/spring-cloud/spring-cloud-kubernetes" target="_top">this repository</a>.</p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_building" href="#_building"></a>12. Building</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_basic_compile_and_test" href="#_basic_compile_and_test"></a>12.1 Basic Compile and Test</h2></div></div></div><p>To build the source you will need to install JDK 1.7.</p><p>Spring Cloud uses Maven for most build-related activities, and you
|
||||||
|
should be able to get off the ground quite quickly by cloning the
|
||||||
|
project you are interested in and typing</p><pre class="screen">$ ./mvnw install</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>You can also install Maven (>=3.3.3) yourself and run the <code class="literal">mvn</code> command
|
||||||
|
in place of <code class="literal">./mvnw</code> in the examples below. If you do that you also
|
||||||
|
might need to add <code class="literal">-P spring</code> if your local Maven settings do not
|
||||||
|
contain repository declarations for spring pre-release artifacts.</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Be aware that you might need to increase the amount of memory
|
||||||
|
available to Maven by setting a <code class="literal">MAVEN_OPTS</code> environment variable with
|
||||||
|
a value like <code class="literal">-Xmx512m -XX:MaxPermSize=128m</code>. We try to cover this in
|
||||||
|
the <code class="literal">.mvn</code> configuration, so if you find you have to do it to make a
|
||||||
|
build succeed, please raise a ticket to get the settings added to
|
||||||
|
source control.</p></td></tr></table></div><p>For hints on how to build the project look in <code class="literal">.travis.yml</code> if there
|
||||||
|
is one. There should be a "script" and maybe "install" command. Also
|
||||||
|
look at the "services" section to see if any services need to be
|
||||||
|
running locally (e.g. mongo or rabbit). Ignore the git-related bits
|
||||||
|
that you might find in "before_install" since they’re related to setting git
|
||||||
|
credentials and you already have those.</p><p>The projects that require middleware generally include a
|
||||||
|
<code class="literal">docker-compose.yml</code>, so consider using
|
||||||
|
<a class="link" href="http://compose.docker.io/" target="_top">Docker Compose</a> to run the middeware servers
|
||||||
|
in Docker containers. See the README in the
|
||||||
|
<a class="link" href="https://github.com/spring-cloud-samples/scripts" target="_top">scripts demo
|
||||||
|
repository</a> for specific instructions about the common cases of mongo,
|
||||||
|
rabbit and redis.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>If all else fails, build with the command from <code class="literal">.travis.yml</code> (usually
|
||||||
|
<code class="literal">./mvnw install</code>).</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_documentation" href="#_documentation"></a>12.2 Documentation</h2></div></div></div><p>The spring-cloud-build module has a "docs" profile, and if you switch
|
||||||
|
that on it will try to build asciidoc sources from
|
||||||
|
<code class="literal">src/main/asciidoc</code>. As part of that process it will look for a
|
||||||
|
<code class="literal">README.adoc</code> and process it by loading all the includes, but not
|
||||||
|
parsing or rendering it, just copying it to <code class="literal">${main.basedir}</code>
|
||||||
|
(defaults to <code class="literal">${basedir}</code>, i.e. the root of the project). If there are
|
||||||
|
any changes in the README it will then show up after a Maven build as
|
||||||
|
a modified file in the correct place. Just commit it and push the change.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_working_with_the_code" href="#_working_with_the_code"></a>12.3 Working with the code</h2></div></div></div><p>If you don’t have an IDE preference we would recommend that you use
|
||||||
|
<a class="link" href="http://www.springsource.com/developer/sts" target="_top">Spring Tools Suite</a> or
|
||||||
|
<a class="link" href="http://eclipse.org" target="_top">Eclipse</a> when working with the code. We use the
|
||||||
|
<a class="link" href="http://eclipse.org/m2e/" target="_top">m2eclipse</a> eclipse plugin for maven support. Other IDEs and tools
|
||||||
|
should also work without issue as long as they use Maven 3.3.3 or better.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_importing_into_eclipse_with_m2eclipse" href="#_importing_into_eclipse_with_m2eclipse"></a>12.3.1 Importing into eclipse with m2eclipse</h3></div></div></div><p>We recommend the <a class="link" href="http://eclipse.org/m2e/" target="_top">m2eclipse</a> eclipse plugin when working with
|
||||||
|
eclipse. If you don’t already have m2eclipse installed it is available from the "eclipse
|
||||||
|
marketplace".</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Older versions of m2e do not support Maven 3.3, so once the
|
||||||
|
projects are imported into Eclipse you will also need to tell
|
||||||
|
m2eclipse to use the right profile for the projects. If you
|
||||||
|
see many different errors related to the POMs in the projects, check
|
||||||
|
that you have an up to date installation. If you can’t upgrade m2e,
|
||||||
|
add the "spring" profile to your <code class="literal">settings.xml</code>. Alternatively you can
|
||||||
|
copy the repository settings from the "spring" profile of the parent
|
||||||
|
pom into your <code class="literal">settings.xml</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_importing_into_eclipse_without_m2eclipse" href="#_importing_into_eclipse_without_m2eclipse"></a>12.3.2 Importing into eclipse without m2eclipse</h3></div></div></div><p>If you prefer not to use m2eclipse you can generate eclipse project metadata using the
|
||||||
|
following command:</p><pre class="screen">$ ./mvnw eclipse:eclipse</pre><p>The generated eclipse projects can be imported by selecting <code class="literal">import existing projects</code>
|
||||||
|
from the <code class="literal">file</code> menu.</p></div></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_contributing" href="#_contributing"></a>13. Contributing</h1></div></div></div><p>Spring Cloud is released under the non-restrictive Apache 2.0 license,
|
||||||
|
and follows a very standard Github development process, using Github
|
||||||
|
tracker for issues and merging pull requests into master. If you want
|
||||||
|
to contribute even something trivial please do not hesitate, but
|
||||||
|
follow the guidelines below.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_sign_the_contributor_license_agreement" href="#_sign_the_contributor_license_agreement"></a>13.1 Sign the Contributor License Agreement</h2></div></div></div><p>Before we accept a non-trivial patch or pull request we will need you to sign the
|
||||||
|
<a class="link" href="https://cla.pivotal.io/sign/spring" target="_top">Contributor License Agreement</a>.
|
||||||
|
Signing the contributor’s agreement does not grant anyone commit rights to the main
|
||||||
|
repository, but it does mean that we can accept your contributions, and you will get an
|
||||||
|
author credit if we do. Active contributors might be asked to join the core team, and
|
||||||
|
given the ability to merge pull requests.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_code_of_conduct" href="#_code_of_conduct"></a>13.2 Code of Conduct</h2></div></div></div><p>This project adheres to the Contributor Covenant <a class="link" href="https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc" target="_top">code of
|
||||||
|
conduct</a>. By participating, you are expected to uphold this code. Please report
|
||||||
|
unacceptable behavior to <a class="link" href="mailto:spring-code-of-conduct@pivotal.io" target="_top">spring-code-of-conduct@pivotal.io</a>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_code_conventions_and_housekeeping" href="#_code_conventions_and_housekeeping"></a>13.3 Code Conventions and Housekeeping</h2></div></div></div><p>None of these is essential for a pull request, but they will all help. They can also be
|
||||||
|
added after the original pull request but before a merge.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Use the Spring Framework code format conventions. If you use Eclipse
|
||||||
|
you can import formatter settings using the
|
||||||
|
<code class="literal">eclipse-code-formatter.xml</code> file from the
|
||||||
|
<a class="link" href="https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml" target="_top">Spring
|
||||||
|
Cloud Build</a> project. If using IntelliJ, you can use the
|
||||||
|
<a class="link" href="http://plugins.jetbrains.com/plugin/6546" target="_top">Eclipse Code Formatter
|
||||||
|
Plugin</a> to import the same file.</li><li class="listitem">Make sure all new <code class="literal">.java</code> files to have a simple Javadoc class comment with at least an
|
||||||
|
<code class="literal">@author</code> tag identifying you, and preferably at least a paragraph on what the class is
|
||||||
|
for.</li><li class="listitem">Add the ASF license header comment to all new <code class="literal">.java</code> files (copy from existing files
|
||||||
|
in the project)</li><li class="listitem">Add yourself as an <code class="literal">@author</code> to the .java files that you modify substantially (more
|
||||||
|
than cosmetic changes).</li><li class="listitem">Add some Javadocs and, if you change the namespace, some XSD doc elements.</li><li class="listitem">A few unit tests would help a lot as well — someone has to do it.</li><li class="listitem">If no-one else is using your branch, please rebase it against the current master (or
|
||||||
|
other target branch in the main project).</li><li class="listitem">When writing a commit message please follow <a class="link" href="http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html" target="_top">these conventions</a>,
|
||||||
|
if you are fixing an existing issue please add <code class="literal">Fixes gh-XXXX</code> at the end of the commit
|
||||||
|
message (where XXXX is the issue number).</li></ul></div></div></div></div></body></html>
|
||||||
841
spring-cloud-kubernetes/1.0.0.RC2/spring-cloud-kubernetes.xml
Normal file
@@ -0,0 +1,841 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<?asciidoc-toc?>
|
||||||
|
<?asciidoc-numbered?>
|
||||||
|
<book xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en">
|
||||||
|
<info>
|
||||||
|
<title>Spring Cloud Kubernetes</title>
|
||||||
|
<date>2018-12-21</date>
|
||||||
|
</info>
|
||||||
|
<chapter xml:id="_why_do_you_need_spring_cloud_kubernetes">
|
||||||
|
<title>Why do you need Spring Cloud Kubernetes?</title>
|
||||||
|
<simpara>Spring Cloud Kubernetes provide Spring Cloud common interfaces implementations to consume Kubernetes native services.
|
||||||
|
The main objective of the projects provided in this repository is to facilitate the integration of Spring Cloud/Spring Boot applications running inside Kubernetes.</simpara>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_discoveryclient_for_kubernetes">
|
||||||
|
<title>DiscoveryClient for Kubernetes</title>
|
||||||
|
<simpara>This project provides an implementation of <link xl:href="https://github.com/spring-cloud/spring-cloud-commons/blob/master/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/DiscoveryClient.java">Discovery Client</link>
|
||||||
|
for <link xl:href="http://kubernetes.io">Kubernetes</link>.
|
||||||
|
This allows you to query Kubernetes endpoints <emphasis role="strong">(see <link xl:href="http://kubernetes.io/docs/user-guide/services/">services</link>)</emphasis> by name.
|
||||||
|
A service is typically exposed by the Kubernetes API server as a collection of endpoints which represent <literal>http</literal>, <literal>https</literal> addresses that a client can
|
||||||
|
access from a Spring Boot application running as a pod. This discovery feature is also used by the Spring Cloud Kubernetes Ribbon project
|
||||||
|
to fetch the list of the endpoints defined for an application to be load balanced.</simpara>
|
||||||
|
<simpara>This is something that you get for free just by adding the following dependency inside your project:</simpara>
|
||||||
|
<programlisting language="xml" linenumbering="unnumbered"><dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-kubernetes</artifactId>
|
||||||
|
<version>${latest.version}</version>
|
||||||
|
</dependency></programlisting>
|
||||||
|
<simpara>To enable loading of the <literal>DiscoveryClient</literal>, add <literal>@EnableDiscoveryClient</literal> to the according configuration or application class like this:</simpara>
|
||||||
|
<programlisting language="java" linenumbering="unnumbered">@SpringBootApplication
|
||||||
|
@EnableDiscoveryClient
|
||||||
|
public class Application {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
}</programlisting>
|
||||||
|
<simpara>Then you can inject the client in your code simply by:</simpara>
|
||||||
|
<programlisting language="java" linenumbering="unnumbered">@Autowired
|
||||||
|
private DiscoveryClient discoveryClient;</programlisting>
|
||||||
|
<simpara>If for any reason you need to disable the <literal>DiscoveryClient</literal> you can simply set the following property in <literal>application.properties</literal>:</simpara>
|
||||||
|
<screen>spring.cloud.kubernetes.discovery.enabled=false</screen>
|
||||||
|
<simpara>Some Spring Cloud components use the <literal>DiscoveryClient</literal> in order to obtain info about the local service instance. For
|
||||||
|
this to work you need to align the Kubernetes service name with the <literal>spring.application.name</literal> property.</simpara>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_kubernetes_native_service_discovery">
|
||||||
|
<title>Kubernetes native service discovery</title>
|
||||||
|
<simpara>Kubernetes itself is capable of (server side) service discovery (see: <link xl:href="https://kubernetes.io/docs/concepts/services-networking/service/#discovering-services">https://kubernetes.io/docs/concepts/services-networking/service/#discovering-services</link>).
|
||||||
|
Using native kubernetes service discovery ensures compatibility with additional tooling, like: istio <link xl:href="https://istio.io">https://istio.io</link> (service mesh, capable of load balancing, ribbon, circuit breaker, failover and much more).</simpara>
|
||||||
|
<simpara>The caller service just needs to refer to names resolvable in particular kubernetes cluster then. Simplest implementation might use the spring <literal>RestTemplate</literal> referring to fully qualified domain name (FQDN) <literal><link xl:href="http://{service-name}.{namespace}.svc.{cluster}.local:{service-port}">http://{service-name}.{namespace}.svc.{cluster}.local:{service-port}</link></literal>.</simpara>
|
||||||
|
<simpara>Additionally, hystrix can be used for:</simpara>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>circuit breaker implementation on the caller side, just by annotating the spring boot application class: <literal>@EnableCircuitBreaker</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>and for the fallback functionality, annotating the respective method via: <literal>@HystrixCommand(fallbackMethod=</literal> does the job.</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_kubernetes_propertysource_implementations">
|
||||||
|
<title>Kubernetes PropertySource implementations</title>
|
||||||
|
<simpara>The most common approach to configure your Spring Boot application is to create an <literal>application.properties|yaml</literal> or
|
||||||
|
an <literal>application-profile.properties|yaml</literal> file containing key-value pairs providing customization values to your
|
||||||
|
application or Spring Boot starters. Users may override these properties by specifying system properties or environment
|
||||||
|
variables.</simpara>
|
||||||
|
<section xml:id="_configmap_propertysource">
|
||||||
|
<title>ConfigMap PropertySource</title>
|
||||||
|
<simpara>Kubernetes provides a resource named <link xl:href="http://kubernetes.io/docs/user-guide/configmap/">ConfigMap</link> to externalize the
|
||||||
|
parameters to pass to your application in the form of key-value pairs or embedded <literal>application.properties|yaml</literal> files.
|
||||||
|
The <link xl:href="./spring-cloud-kubernetes-config">Spring Cloud Kubernetes Config</link> project makes Kubernetes `ConfigMap`s available
|
||||||
|
during application bootstrapping and triggers hot reloading of beans or Spring context when changes are detected on
|
||||||
|
observed `ConfigMap`s.</simpara>
|
||||||
|
<simpara>The default behavior is to create a <literal>ConfigMapPropertySource</literal> based on a Kubernetes <literal>ConfigMap</literal> which has <literal>metadata.name</literal> of either the name of
|
||||||
|
your Spring application (as defined by its <literal>spring.application.name</literal> property) or a custom name defined within the
|
||||||
|
<literal>bootstrap.properties</literal> file under the following key <literal>spring.cloud.kubernetes.config.name</literal>.</simpara>
|
||||||
|
<simpara>However, more advanced configuration are possible where multiple ConfigMaps can be used
|
||||||
|
This is made possible by the <literal>spring.cloud.kubernetes.config.sources</literal> list.
|
||||||
|
For example one could define the following ConfigMaps</simpara>
|
||||||
|
<programlisting language="yaml" linenumbering="unnumbered">spring:
|
||||||
|
application:
|
||||||
|
name: cloud-k8s-app
|
||||||
|
cloud:
|
||||||
|
kubernetes:
|
||||||
|
config:
|
||||||
|
name: default-name
|
||||||
|
namespace: default-namespace
|
||||||
|
sources:
|
||||||
|
# Spring Cloud Kubernetes will lookup a ConfigMap named c1 in namespace default-namespace
|
||||||
|
- name: c1
|
||||||
|
# Spring Cloud Kubernetes will lookup a ConfigMap named default-name in whatever namespace n2
|
||||||
|
- namespace: n2
|
||||||
|
# Spring Cloud Kubernetes will lookup a ConfigMap named c3 in namespace n3
|
||||||
|
- namespace: n3
|
||||||
|
name: c3</programlisting>
|
||||||
|
<simpara>In the example above, it <literal>spring.cloud.kubernetes.config.namespace</literal> had not been set,
|
||||||
|
then the ConfigMap named <literal>c1</literal> would be looked up in the namespace that the application runs</simpara>
|
||||||
|
<simpara>Any matching <literal>ConfigMap</literal> that is found, will be processed as follows:</simpara>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>apply individual configuration properties.</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>apply as <literal>yaml</literal> the content of any property named <literal>application.yaml</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>apply as properties file the content of any property named <literal>application.properties</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<simpara>The single exception to the aforementioned flow is when the <literal>ConfigMap</literal> contains a <emphasis role="strong">single</emphasis> key that indicates
|
||||||
|
the file is a YAML or Properties file. In that case the name of the key does NOT have to be <literal>application.yaml</literal> or
|
||||||
|
<literal>application.properties</literal> (it can be anything) and the value of the property will be treated correctly.
|
||||||
|
This features facilitates the use case where the <literal>ConfigMap</literal> was created using something like:</simpara>
|
||||||
|
<simpara><literal>kubectl create configmap game-config --from-file=/path/to/app-config.yaml</literal></simpara>
|
||||||
|
<simpara>Example:</simpara>
|
||||||
|
<simpara>Let’s assume that we have a Spring Boot application named <literal>demo</literal> that uses properties to read its thread pool
|
||||||
|
configuration.</simpara>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>pool.size.core</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>pool.size.maximum</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<simpara>This can be externalized to config map in <literal>yaml</literal> format:</simpara>
|
||||||
|
<programlisting language="yaml" linenumbering="unnumbered">kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: demo
|
||||||
|
data:
|
||||||
|
pool.size.core: 1
|
||||||
|
pool.size.max: 16</programlisting>
|
||||||
|
<simpara>Individual properties work fine for most cases but sometimes embedded <literal>yaml</literal> is more convenient. In this case we will
|
||||||
|
use a single property named <literal>application.yaml</literal> to embed our <literal>yaml</literal>:</simpara>
|
||||||
|
<literallayout class="monospaced"> ```yaml
|
||||||
|
kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: demo
|
||||||
|
data:
|
||||||
|
application.yaml: |-
|
||||||
|
pool:
|
||||||
|
size:
|
||||||
|
core: 1
|
||||||
|
max:16</literallayout>
|
||||||
|
<screen>The following also works:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: demo
|
||||||
|
data:
|
||||||
|
custom-name.yaml: |-
|
||||||
|
pool:
|
||||||
|
size:
|
||||||
|
core: 1
|
||||||
|
max:16</screen>
|
||||||
|
<simpara>Spring Boot applications can also be configured differently depending on active profiles which will be merged together
|
||||||
|
when the ConfigMap is read. It is possible to provide different property values for different profiles using an
|
||||||
|
<literal>application.properties|yaml</literal> property, specifying profile-specific values each in their own document
|
||||||
|
(indicated by the <literal>---</literal> sequence) as follows:</simpara>
|
||||||
|
<programlisting language="yaml" linenumbering="unnumbered">kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: demo
|
||||||
|
data:
|
||||||
|
application.yml: |-
|
||||||
|
greeting:
|
||||||
|
message: Say Hello to the World
|
||||||
|
farewell:
|
||||||
|
message: Say Goodbye
|
||||||
|
---
|
||||||
|
spring:
|
||||||
|
profiles: development
|
||||||
|
greeting:
|
||||||
|
message: Say Hello to the Developers
|
||||||
|
farewell:
|
||||||
|
message: Say Goodbye to the Developers
|
||||||
|
---
|
||||||
|
spring:
|
||||||
|
profiles: production
|
||||||
|
greeting:
|
||||||
|
message: Say Hello to the Ops</programlisting>
|
||||||
|
<simpara>In the above case, the configuration loaded into your Spring Application with the <literal>development</literal> profile will be:</simpara>
|
||||||
|
<programlisting language="yaml" linenumbering="unnumbered"> greeting:
|
||||||
|
message: Say Hello to the Developers
|
||||||
|
farewell:
|
||||||
|
message: Say Goodbye to the Developers</programlisting>
|
||||||
|
<simpara>whereas if the <literal>production</literal> profile is active, the configuration will be:</simpara>
|
||||||
|
<programlisting language="yaml" linenumbering="unnumbered"> greeting:
|
||||||
|
message: Say Hello to the Ops
|
||||||
|
farewell:
|
||||||
|
message: Say Goodbye</programlisting>
|
||||||
|
<simpara>If both profiles are active, the property which appears last within the configmap will overwrite preceding values.</simpara>
|
||||||
|
<simpara>To tell to Spring Boot which <literal>profile</literal> should be enabled at bootstrap, a system property can be passed to the Java
|
||||||
|
command launching your Spring Boot application using an env variable that you will define with the OpenShift
|
||||||
|
<literal>DeploymentConfig</literal> or Kubernetes <literal>ReplicationConfig</literal> resource file as follows:</simpara>
|
||||||
|
<programlisting language="yaml" linenumbering="unnumbered">apiVersion: v1
|
||||||
|
kind: DeploymentConfig
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
...
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- env:
|
||||||
|
- name: JAVA_APP_DIR
|
||||||
|
value: /deployments
|
||||||
|
- name: JAVA_OPTIONS
|
||||||
|
value: -Dspring.profiles.active=developer</programlisting>
|
||||||
|
<simpara><emphasis role="strong">Notes:</emphasis>
|
||||||
|
- check the security configuration section, to access config maps from inside a pod you need to have the correct
|
||||||
|
Kubernetes service accounts, roles and role bindings.</simpara>
|
||||||
|
<simpara>Another option for using ConfigMaps, is to mount them into the Pod running the Spring Cloud Kubernetes application
|
||||||
|
and have Spring Cloud Kubernetes read them from the file system.
|
||||||
|
This behavior is controlled by the <literal>spring.cloud.kubernetes.config.paths</literal> property and can be used in
|
||||||
|
addition to or instead of the mechanism described earlier.
|
||||||
|
Multiple (exact) file paths can be specified in <literal>spring.cloud.kubernetes.config.paths</literal> by using the <literal>,</literal> delimiter</simpara>
|
||||||
|
<table frame="all" rowsep="1" colsep="1">
|
||||||
|
<title>Properties:</title>
|
||||||
|
<tgroup cols="4">
|
||||||
|
<colspec colname="col_1" colwidth="25*"/>
|
||||||
|
<colspec colname="col_2" colwidth="25*"/>
|
||||||
|
<colspec colname="col_3" colwidth="25*"/>
|
||||||
|
<colspec colname="col_4" colwidth="25*"/>
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top">Name</entry>
|
||||||
|
<entry align="left" valign="top">Type</entry>
|
||||||
|
<entry align="left" valign="top">Default</entry>
|
||||||
|
<entry align="left" valign="top">Description</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.config.enabled</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Boolean</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>true</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Enable Secrets PropertySource</simpara></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.config.name</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>String</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>${spring.application.name}</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Sets the name of ConfigMap to lookup</simpara></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.config.namespace</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>String</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Client namespace</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Sets the Kubernetes namespace where to lookup</simpara></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.config.paths</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>List</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>null</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Sets the paths where ConfigMaps are mounted</simpara></entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.config.enableApi</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Boolean</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>true</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Enable/Disable consuming ConfigMaps via APIs</simpara></entry>
|
||||||
|
</row>
|
||||||
|
</tfoot>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
<section xml:id="_secrets_propertysource">
|
||||||
|
<title>Secrets PropertySource</title>
|
||||||
|
<simpara>Kubernetes has the notion of [Secrets](<link xl:href="https://kubernetes.io/docs/concepts/configuration/secret/">https://kubernetes.io/docs/concepts/configuration/secret/</link>) for storing
|
||||||
|
sensitive data such as password, OAuth tokens, etc. This project provides integration with <literal>Secrets</literal> to make secrets
|
||||||
|
accessible by Spring Boot applications. This feature can be explicitly enabled/disabled using the <literal>spring.cloud.kubernetes.secrets.enabled</literal> property.</simpara>
|
||||||
|
<simpara>The <literal>SecretsPropertySource</literal> when enabled will lookup Kubernetes for <literal>Secrets</literal> from the following sources:
|
||||||
|
1. reading recursively from secrets mounts
|
||||||
|
2. named after the application (as defined by <literal>spring.application.name</literal>)
|
||||||
|
3. matching some labels</simpara>
|
||||||
|
<simpara>Please note that by default, consuming Secrets via API (points 2 and 3 above) <emphasis role="strong">is not enabled</emphasis> for security reasons
|
||||||
|
and it is recommend that containers share secrets via mounted volumes. Otherwise proper RBAC security configurations must be provided
|
||||||
|
to make sure that unauthorized access to Secrets occurs.</simpara>
|
||||||
|
<simpara>If the secrets are found their data is made available to the application.</simpara>
|
||||||
|
<simpara><emphasis role="strong">Example:</emphasis></simpara>
|
||||||
|
<simpara>Let’s assume that we have a spring boot application named <literal>demo</literal> that uses properties to read its database
|
||||||
|
configuration. We can create a Kubernetes secret using the following command:</simpara>
|
||||||
|
<screen>oc create secret generic db-secret --from-literal=username=user --from-literal=password=p455w0rd</screen>
|
||||||
|
<simpara>This would create the following secret (shown using <literal>oc get secrets db-secret -o yaml</literal>):</simpara>
|
||||||
|
<programlisting language="yaml" linenumbering="unnumbered">apiVersion: v1
|
||||||
|
data:
|
||||||
|
password: cDQ1NXcwcmQ=
|
||||||
|
username: dXNlcg==
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: 2017-07-04T09:15:57Z
|
||||||
|
name: db-secret
|
||||||
|
namespace: default
|
||||||
|
resourceVersion: "357496"
|
||||||
|
selfLink: /api/v1/namespaces/default/secrets/db-secret
|
||||||
|
uid: 63c89263-6099-11e7-b3da-76d6186905a8
|
||||||
|
type: Opaque</programlisting>
|
||||||
|
<simpara>Note that the data contains Base64-encoded versions of the literal provided by the create command.</simpara>
|
||||||
|
<simpara>This secret can then be used by your application for example by exporting the secret’s value as environment variables:</simpara>
|
||||||
|
<programlisting language="yaml" linenumbering="unnumbered">apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: ${project.artifactId}
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- env:
|
||||||
|
- name: DB_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: db-secret
|
||||||
|
key: username
|
||||||
|
- name: DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: db-secret
|
||||||
|
key: password</programlisting>
|
||||||
|
<simpara>You can select the Secrets to consume in a number of ways:</simpara>
|
||||||
|
<orderedlist numeration="arabic">
|
||||||
|
<listitem>
|
||||||
|
<simpara>By listing the directories where secrets are mapped:
|
||||||
|
<literal>`
|
||||||
|
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets/db-secret,etc/secrets/postgresql
|
||||||
|
</literal>`</simpara>
|
||||||
|
<literallayout class="monospaced">If you have all the secrets mapped to a common root, you can set them like:</literallayout>
|
||||||
|
<literallayout class="monospaced">```
|
||||||
|
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets
|
||||||
|
```</literallayout>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>By setting a named secret:
|
||||||
|
<literal>`
|
||||||
|
-Dspring.cloud.kubernetes.secrets.name=db-secret
|
||||||
|
</literal>`</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>By defining a list of labels:
|
||||||
|
<literal>`
|
||||||
|
-Dspring.cloud.kubernetes.secrets.labels.broker=activemq
|
||||||
|
-Dspring.cloud.kubernetes.secrets.labels.db=postgresql
|
||||||
|
</literal>`</simpara>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist>
|
||||||
|
<table frame="all" rowsep="1" colsep="1">
|
||||||
|
<title>Properties:</title>
|
||||||
|
<tgroup cols="4">
|
||||||
|
<colspec colname="col_1" colwidth="25*"/>
|
||||||
|
<colspec colname="col_2" colwidth="25*"/>
|
||||||
|
<colspec colname="col_3" colwidth="25*"/>
|
||||||
|
<colspec colname="col_4" colwidth="25*"/>
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top">Name</entry>
|
||||||
|
<entry align="left" valign="top">Type</entry>
|
||||||
|
<entry align="left" valign="top">Default</entry>
|
||||||
|
<entry align="left" valign="top">Description</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.secrets.enabled</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Boolean</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>true</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Enable Secrets PropertySource</simpara></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.secrets.name</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>String</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>${spring.application.name}</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Sets the name of the secret to lookup</simpara></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.secrets.namespace</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>String</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Client namespace</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Sets the Kubernetes namespace where to lookup</simpara></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.secrets.labels</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Map</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>null</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Sets the labels used to lookup secrets</simpara></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.secrets.paths</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>List</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>null</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Sets the paths where secrets are mounted (example 1)</simpara></entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.secrets.enableApi</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Boolean</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>false</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Enable/Disable consuming secrets via APIs (examples 2 and 3)</simpara></entry>
|
||||||
|
</row>
|
||||||
|
</tfoot>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
<simpara><emphasis role="strong">Notes:</emphasis>
|
||||||
|
- The property <literal>spring.cloud.kubernetes.secrets.labels</literal> behaves as defined by
|
||||||
|
<link xl:href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding#map-based-binding">Map-based binding</link>.
|
||||||
|
- The property <literal>spring.cloud.kubernetes.secrets.paths</literal> behaves as defined by
|
||||||
|
<link xl:href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding#collection-based-binding">Collection-based binding</link>.
|
||||||
|
- Access to secrets via API may be restricted for security reasons, the preferred way is to mount secret to the POD.</simpara>
|
||||||
|
<simpara>Example of application using secrets (though it hasn’t been updated to use the new <literal>spring-cloud-kubernetes</literal> project):
|
||||||
|
<link xl:href="https://github.com/fabric8-quickstarts/spring-boot-camel-config">spring-boot-camel-config</link></simpara>
|
||||||
|
</section>
|
||||||
|
<section xml:id="_propertysource_reload">
|
||||||
|
<title>PropertySource Reload</title>
|
||||||
|
<simpara>Some applications may need to detect changes on external property sources and update their internal status to reflect the new configuration.
|
||||||
|
The reload feature of Spring Cloud Kubernetes is able to trigger an application reload when a related <literal>ConfigMap</literal> or
|
||||||
|
<literal>Secret</literal> changes.</simpara>
|
||||||
|
<simpara>This feature is disabled by default and can be enabled using the configuration property <literal>spring.cloud.kubernetes.reload.enabled=true</literal>
|
||||||
|
(eg. in the <emphasis role="strong">application.properties</emphasis> file).</simpara>
|
||||||
|
<simpara>The following levels of reload are supported (property <literal>spring.cloud.kubernetes.reload.strategy</literal>):
|
||||||
|
- <emphasis role="strong"><literal>refresh</literal> (default)</emphasis>: only configuration beans annotated with <literal>@ConfigurationProperties</literal> or <literal>@RefreshScope</literal> are reloaded.
|
||||||
|
This reload level leverages the refresh feature of Spring Cloud Context.
|
||||||
|
- <emphasis role="strong"><literal>restart_context</literal></emphasis>: the whole Spring <emphasis>ApplicationContext</emphasis> is gracefully restarted. Beans are recreated with the new configuration.
|
||||||
|
- <emphasis role="strong"><literal>shutdown</literal></emphasis>: the Spring <emphasis>ApplicationContext</emphasis> is shut down to activate a restart of the container.
|
||||||
|
When using this level, make sure that the lifecycle of all non-daemon threads is bound to the ApplicationContext
|
||||||
|
and that a replication controller or replica set is configured to restart the pod.</simpara>
|
||||||
|
<simpara>Example:</simpara>
|
||||||
|
<simpara>Assuming that the reload feature is enabled with default settings (<emphasis role="strong"><literal>refresh</literal></emphasis> mode), the following bean will be refreshed when the config map changes:</simpara>
|
||||||
|
<programlisting language="java" linenumbering="unnumbered">@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "bean")
|
||||||
|
public class MyConfig {
|
||||||
|
|
||||||
|
private String message = "a message that can be changed live";
|
||||||
|
|
||||||
|
// getter and setters
|
||||||
|
|
||||||
|
}</programlisting>
|
||||||
|
<simpara>A way to see that changes effectively happen is creating another bean that prints the message periodically.</simpara>
|
||||||
|
<programlisting language="java" linenumbering="unnumbered">@Component
|
||||||
|
public class MyBean {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MyConfig config;
|
||||||
|
|
||||||
|
@Scheduled(fixedDelay = 5000)
|
||||||
|
public void hello() {
|
||||||
|
System.out.println("The message is: " + config.getMessage());
|
||||||
|
}
|
||||||
|
}</programlisting>
|
||||||
|
<simpara>The message printed by the application can be changed using a <literal>ConfigMap</literal> as follows:</simpara>
|
||||||
|
<programlisting language="yaml" linenumbering="unnumbered">apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: reload-example
|
||||||
|
data:
|
||||||
|
application.properties: |-
|
||||||
|
bean.message=Hello World!</programlisting>
|
||||||
|
<simpara>Any change to the property named <literal>bean.message</literal> in the <literal>ConfigMap</literal> associated to the pod will be reflected in the
|
||||||
|
output. More generally speaking, changes associated to properties prefixed with the value defined by the <literal>prefix</literal>
|
||||||
|
field of the <literal>@ConfigurationProperties</literal> annotation will be detected and reflected in the application.
|
||||||
|
[Associating a <literal>ConfigMap</literal> to a pod](#configmap-propertysource) is explained above.</simpara>
|
||||||
|
<simpara>The full example is available in [spring-cloud-kubernetes-reload-example](spring-cloud-kubernetes-examples/kubernetes-reload-example).</simpara>
|
||||||
|
<simpara>The reload feature supports two operating modes:
|
||||||
|
- <emphasis role="strong">event (default)</emphasis>: watches for changes in config maps or secrets using the Kubernetes API (web socket).
|
||||||
|
Any event will produce a re-check on the configuration and a reload in case of changes.
|
||||||
|
The <literal>view</literal> role on the service account is required in order to listen for config map changes. A higher level role (eg. <literal>edit</literal>) is required for secrets
|
||||||
|
(secrets are not monitored by default).
|
||||||
|
- <emphasis role="strong">polling</emphasis>: re-creates the configuration periodically from config maps and secrets to see if it has changed.
|
||||||
|
The polling period can be configured using the property <literal>spring.cloud.kubernetes.reload.period</literal> and defaults to <emphasis role="strong">15 seconds</emphasis>.
|
||||||
|
It requires the same role as the monitored property source.
|
||||||
|
This means, for example, that using polling on file mounted secret sources does not require particular privileges.</simpara>
|
||||||
|
<table frame="all" rowsep="1" colsep="1">
|
||||||
|
<title>Properties:</title>
|
||||||
|
<tgroup cols="4">
|
||||||
|
<colspec colname="col_1" colwidth="25*"/>
|
||||||
|
<colspec colname="col_2" colwidth="25*"/>
|
||||||
|
<colspec colname="col_3" colwidth="25*"/>
|
||||||
|
<colspec colname="col_4" colwidth="25*"/>
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top">Name</entry>
|
||||||
|
<entry align="left" valign="top">Type</entry>
|
||||||
|
<entry align="left" valign="top">Default</entry>
|
||||||
|
<entry align="left" valign="top">Description</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.reload.enabled</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Boolean</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>false</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Enables monitoring of property sources and configuration reload</simpara></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.reload.monitoring-config-maps</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Boolean</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>true</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Allow monitoring changes in config maps</simpara></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.reload.monitoring-secrets</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Boolean</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>false</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Allow monitoring changes in secrets</simpara></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.reload.strategy</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Enum</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>refresh</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>The strategy to use when firing a reload (<emphasis role="strong">refresh</emphasis>, <emphasis role="strong">restart_context</emphasis>, <emphasis role="strong">shutdown</emphasis>)</simpara></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.reload.mode</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Enum</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>event</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Specifies how to listen for changes in property sources (<emphasis role="strong">event</emphasis>, <emphasis role="strong">polling</emphasis>)</simpara></entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<row>
|
||||||
|
<entry align="left" valign="top"><simpara>spring.cloud.kubernetes.reload.period</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>Duration</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>15s</simpara></entry>
|
||||||
|
<entry align="left" valign="top"><simpara>The period for verifying changes when using the <emphasis role="strong">polling</emphasis> strategy</simpara></entry>
|
||||||
|
</row>
|
||||||
|
</tfoot>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
<simpara><emphasis role="strong">Notes</emphasis>:
|
||||||
|
- Properties under <emphasis role="strong">spring.cloud.kubernetes.reload.</emphasis> should not be used in config maps or secrets: changing such properties at runtime may lead to unexpected results;
|
||||||
|
- Deleting a property or the whole config map does not restore the original state of the beans when using the <emphasis role="strong">refresh</emphasis> level.</simpara>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_ribbon_discovery_in_kubernetes">
|
||||||
|
<title>Ribbon discovery in Kubernetes</title>
|
||||||
|
<simpara>Spring Cloud client applications calling a microservice should be interested on relying on a client load-balancing
|
||||||
|
feature in order to automatically discover at which endpoint(s) it can reach a given service. This mechanism has been
|
||||||
|
implemented within the [spring-cloud-kubernetes-ribbon](spring-cloud-kubernetes-ribbon/pom.xml) project where a
|
||||||
|
Kubernetes client will populate a <link xl:href="https://github.com/Netflix/ribbon">Ribbon</link> <literal>ServerList</literal> containing information
|
||||||
|
about such endpoints.</simpara>
|
||||||
|
<simpara>The implementation is part of the following starter that you can use by adding its dependency to your pom file:</simpara>
|
||||||
|
<programlisting language="xml" linenumbering="unnumbered"><dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
|
||||||
|
<version>${latest.version}</version>
|
||||||
|
</dependency></programlisting>
|
||||||
|
<simpara>When the list of the endpoints is populated, the Kubernetes client will search the registered endpoints living in
|
||||||
|
the current namespace/project matching the service name defined using the Ribbon Client annotation:</simpara>
|
||||||
|
<programlisting language="java" linenumbering="unnumbered">@RibbonClient(name = "name-service")</programlisting>
|
||||||
|
<simpara>You can configure Ribbon’s behavior by providing properties in your <literal>application.properties</literal> (via your application’s
|
||||||
|
dedicated <literal>ConfigMap</literal>) using the following format: <literal><name of your service>.ribbon.<Ribbon configuration key></literal> where:</simpara>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><name of your service></literal> corresponds to the service name you’re accessing over Ribbon, as configured using the
|
||||||
|
<literal>@RibbonClient</literal> annotation (e.g. <literal>name-service</literal> in the example above)</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><Ribbon configuration key></literal> is one of the Ribbon configuration key defined by
|
||||||
|
<link xl:href="https://github.com/Netflix/ribbon/blob/master/ribbon-core/src/main/java/com/netflix/client/config/CommonClientConfigKey.java">Ribbon’s CommonClientConfigKey class</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<simpara>Additionally, the <literal>spring-cloud-kubernetes-ribbon</literal> project defines two additional configuration keys to further
|
||||||
|
control how Ribbon interacts with Kubernetes. In particular, if an endpoint defines multiple ports, the default
|
||||||
|
behavior is to use the first one found. To select more specifically which port to use, in a multi-port service, use
|
||||||
|
the <literal>PortName</literal> key. If you want to specify in which Kubernetes' namespace the target service should be looked up, use
|
||||||
|
the <literal>KubernetesNamespace</literal> key, remembering in both instances to prefix these keys with your service name and
|
||||||
|
<literal>ribbon</literal> prefix as specified above.</simpara>
|
||||||
|
<simpara>Examples that are using this module for ribbon discovery are:</simpara>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara><link xl:href="./spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example">Spring Cloud Circuitbreaker and Ribbon</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><link xl:href="https://github.com/fabric8-quickstarts/spring-boot-ribbon">fabric8-quickstarts - Spring Boot - Ribbon</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><link xl:href="https://github.com/fabric8io/kubeflix/tree/master/examples/loanbroker/bank">Kubeflix - LoanBroker - Bank</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<simpara><emphasis role="strong">Note</emphasis>: The Ribbon discovery client can be disabled by setting this key within the application properties file
|
||||||
|
<literal>spring.cloud.kubernetes.ribbon.enabled=false</literal>.</simpara>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_kubernetes_ecosystem_awareness">
|
||||||
|
<title>Kubernetes Ecosystem Awareness</title>
|
||||||
|
<simpara>All of the features described above will work equally well regardless of whether your application is running inside
|
||||||
|
Kubernetes or not. This is really helpful for development and troubleshooting.
|
||||||
|
From a development point of view, this is really helpful as you can start your Spring Boot application and debug one
|
||||||
|
of the modules part of this project. It is not required to deploy it in Kubernetes
|
||||||
|
as the code of the project relies on the
|
||||||
|
<link xl:href="https://github.com/fabric8io/kubernetes-client">Fabric8 Kubernetes Java client</link> which is a fluent DSL able to
|
||||||
|
communicate using <literal>http</literal> protocol to the REST API of Kubernetes Server.</simpara>
|
||||||
|
<section xml:id="_kubernetes_profile_autoconfiguration">
|
||||||
|
<title>Kubernetes Profile Autoconfiguration</title>
|
||||||
|
<simpara>When the application runs as a pod inside Kubernetes a Spring profile named <literal>kubernetes</literal> will automatically get activated.
|
||||||
|
This allows the developer to customize the configuration, to define beans that will be applied when the Spring Boot application is deployed
|
||||||
|
within the Kubernetes platform <emphasis role="strong">(e.g. different dev and prod configuration)</emphasis>.</simpara>
|
||||||
|
</section>
|
||||||
|
<section xml:id="_istio_awareness">
|
||||||
|
<title>Istio Awareness</title>
|
||||||
|
<simpara>When including the <emphasis role="strong">spring-cloud-kubernetes-istio</emphasis> module into the application classpath a new profile will be added to the application,
|
||||||
|
if the application is running inside a Kubernetes Cluster with <link xl:href="http://istio.io">Istio</link> installed. Then you can use
|
||||||
|
spring <emphasis role="strong">@Profile("istio")</emphasis> annotations into your Beans and <emphasis role="strong">@Configuration</emphasis>'s.</simpara>
|
||||||
|
<simpara>The Istio awareness module uses the <emphasis role="strong">me.snowdrop:istio-client</emphasis> to interact with Istio APIs enabling us to discover traffic rules, circuit breakers, etc.
|
||||||
|
Making it easy for our Spring Boot applications to consume this data to dynamically configure themselves according the environment.</simpara>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_pod_health_indicator">
|
||||||
|
<title>Pod Health Indicator</title>
|
||||||
|
<simpara>Spring Boot uses <link xl:href="https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpoint.java">HealthIndicator</link> to expose info about the health of an application.
|
||||||
|
That makes it really useful for exposing health related information to the user and are also a good fit for use as <link xl:href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/">readiness probes</link>.</simpara>
|
||||||
|
<simpara>The Kubernetes health indicator which is part of the core module exposes the following info:</simpara>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>pod name, ip address, namespace, service account, node name and its ip address</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>flag that indicates if the Spring Boot application is internal or external to Kubernetes</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_leader_election">
|
||||||
|
<title>Leader Election</title>
|
||||||
|
<simpara><TBD></simpara>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_security_configurations_inside_kubernetes">
|
||||||
|
<title>Security Configurations inside Kubernetes</title>
|
||||||
|
<section xml:id="_namespace">
|
||||||
|
<title>Namespace</title>
|
||||||
|
<simpara>Most of the components provided in this project need to know the namespace. For Kubernetes (1.3+) the namespace is made available to pod as part of the service account secret and automatically detected by the client.
|
||||||
|
For earlier version it needs to be specified as an env var to the pod. A quick way to do this is:</simpara>
|
||||||
|
<literallayout class="monospaced">env:
|
||||||
|
- name: "KUBERNETES_NAMESPACE"
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: "metadata.namespace"</literallayout>
|
||||||
|
</section>
|
||||||
|
<section xml:id="_service_account">
|
||||||
|
<title>Service Account</title>
|
||||||
|
<simpara>For distros of Kubernetes that support more fine-grained role-based access within the cluster, you need to make sure a pod that runs with spring-cloud-kubernetes has access to the Kubernetes API.
|
||||||
|
For any service accounts you assign to a deployment/pod, you need to make sure it has the correct roles. For example, you can add <literal>cluster-reader</literal> permissions to your <literal>default</literal> service account depending on the project you’re in:</simpara>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_examples">
|
||||||
|
<title>Examples</title>
|
||||||
|
<simpara>Spring Cloud Kubernetes tries to make it transparent for your applications to consume Kubernetes Native Services
|
||||||
|
following the Spring Cloud interfaces.</simpara>
|
||||||
|
<simpara>In your applications, you need to add the <emphasis role="strong">spring-cloud-kubernetes-discovery</emphasis> dependency to your classpath and remove any other dependency that contains a <emphasis role="strong">DiscoveryClient</emphasis> implementation (ie. Eureka Discovery Client).
|
||||||
|
The same applies for PropertySourceLocator, where you need to add to the classpath the <emphasis role="strong">spring-cloud-kubernetes-config</emphasis> and remove any other dependency that contains a <emphasis role="strong">PropertySourceLocator</emphasis> implementation (ie. Config Server Client).</simpara>
|
||||||
|
<simpara>The following projects highlight the usage of these dependencies and demonstrate how these libraries can be used from any Spring Boot application.</simpara>
|
||||||
|
<simpara>List of examples using these projects:</simpara>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara><link xl:href="https://github.com/spring-cloud/spring-cloud-kubernetes/tree/master/spring-cloud-kubernetes-examples">Spring Cloud Kubernetes Examples</link>: the ones located inside this repository.</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>Spring Cloud Kubernetes Full Example: Minions and Boss</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><link xl:href="https://github.com/salaboy/spring-cloud-k8s-minion">Minion</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><link xl:href="https://github.com/salaboy/spring-cloud-k8s-boss">Boss</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>Spring Cloud Kubernetes Full Example: <link xl:href="https://github.com/salaboy/s1p_docs">SpringOne Platform Tickets Service</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><link xl:href="https://github.com/salaboy/s1p_gateway">Spring Cloud Gateway with Spring Cloud Kubernetes Discovery and Config</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><link xl:href="https://github.com/salaboy/showcase-admin-tool">Spring Boot Admin with Spring Cloud Kubernetes Discovery and Config</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_other_resources">
|
||||||
|
<title>Other Resources</title>
|
||||||
|
<simpara>Here you can find other resources such as presentations(slides) and videos about Spring Cloud Kubernetes.</simpara>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara><link xl:href="https://salaboy.com/2018/09/27/the-s1p-experience/">S1P Spring Cloud on PKS</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><link xl:href="https://salaboy.com/2018/07/18/ljc-july-18-spring-cloud-docker-k8s/">Spring Cloud, Docker, Kubernetes → London Java Community July 2018</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<simpara>Please feel free to submit other resources via PR to <link xl:href="http://github.com/spring-cloud/spring-cloud-kubernetes">this repository</link>.</simpara>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_building">
|
||||||
|
<title>Building</title>
|
||||||
|
<section xml:id="_basic_compile_and_test">
|
||||||
|
<title>Basic Compile and Test</title>
|
||||||
|
<simpara>To build the source you will need to install JDK 1.7.</simpara>
|
||||||
|
<simpara>Spring Cloud uses Maven for most build-related activities, and you
|
||||||
|
should be able to get off the ground quite quickly by cloning the
|
||||||
|
project you are interested in and typing</simpara>
|
||||||
|
<screen>$ ./mvnw install</screen>
|
||||||
|
<note>
|
||||||
|
<simpara>You can also install Maven (>=3.3.3) yourself and run the <literal>mvn</literal> command
|
||||||
|
in place of <literal>./mvnw</literal> in the examples below. If you do that you also
|
||||||
|
might need to add <literal>-P spring</literal> if your local Maven settings do not
|
||||||
|
contain repository declarations for spring pre-release artifacts.</simpara>
|
||||||
|
</note>
|
||||||
|
<note>
|
||||||
|
<simpara>Be aware that you might need to increase the amount of memory
|
||||||
|
available to Maven by setting a <literal>MAVEN_OPTS</literal> environment variable with
|
||||||
|
a value like <literal>-Xmx512m -XX:MaxPermSize=128m</literal>. We try to cover this in
|
||||||
|
the <literal>.mvn</literal> configuration, so if you find you have to do it to make a
|
||||||
|
build succeed, please raise a ticket to get the settings added to
|
||||||
|
source control.</simpara>
|
||||||
|
</note>
|
||||||
|
<simpara>For hints on how to build the project look in <literal>.travis.yml</literal> if there
|
||||||
|
is one. There should be a "script" and maybe "install" command. Also
|
||||||
|
look at the "services" section to see if any services need to be
|
||||||
|
running locally (e.g. mongo or rabbit). Ignore the git-related bits
|
||||||
|
that you might find in "before_install" since they’re related to setting git
|
||||||
|
credentials and you already have those.</simpara>
|
||||||
|
<simpara>The projects that require middleware generally include a
|
||||||
|
<literal>docker-compose.yml</literal>, so consider using
|
||||||
|
<link xl:href="http://compose.docker.io/">Docker Compose</link> to run the middeware servers
|
||||||
|
in Docker containers. See the README in the
|
||||||
|
<link xl:href="https://github.com/spring-cloud-samples/scripts">scripts demo
|
||||||
|
repository</link> for specific instructions about the common cases of mongo,
|
||||||
|
rabbit and redis.</simpara>
|
||||||
|
<note>
|
||||||
|
<simpara>If all else fails, build with the command from <literal>.travis.yml</literal> (usually
|
||||||
|
<literal>./mvnw install</literal>).</simpara>
|
||||||
|
</note>
|
||||||
|
</section>
|
||||||
|
<section xml:id="_documentation">
|
||||||
|
<title>Documentation</title>
|
||||||
|
<simpara>The spring-cloud-build module has a "docs" profile, and if you switch
|
||||||
|
that on it will try to build asciidoc sources from
|
||||||
|
<literal>src/main/asciidoc</literal>. As part of that process it will look for a
|
||||||
|
<literal>README.adoc</literal> and process it by loading all the includes, but not
|
||||||
|
parsing or rendering it, just copying it to <literal>${main.basedir}</literal>
|
||||||
|
(defaults to <literal>${basedir}</literal>, i.e. the root of the project). If there are
|
||||||
|
any changes in the README it will then show up after a Maven build as
|
||||||
|
a modified file in the correct place. Just commit it and push the change.</simpara>
|
||||||
|
</section>
|
||||||
|
<section xml:id="_working_with_the_code">
|
||||||
|
<title>Working with the code</title>
|
||||||
|
<simpara>If you don’t have an IDE preference we would recommend that you use
|
||||||
|
<link xl:href="http://www.springsource.com/developer/sts">Spring Tools Suite</link> or
|
||||||
|
<link xl:href="http://eclipse.org">Eclipse</link> when working with the code. We use the
|
||||||
|
<link xl:href="http://eclipse.org/m2e/">m2eclipse</link> eclipse plugin for maven support. Other IDEs and tools
|
||||||
|
should also work without issue as long as they use Maven 3.3.3 or better.</simpara>
|
||||||
|
<section xml:id="_importing_into_eclipse_with_m2eclipse">
|
||||||
|
<title>Importing into eclipse with m2eclipse</title>
|
||||||
|
<simpara>We recommend the <link xl:href="http://eclipse.org/m2e/">m2eclipse</link> eclipse plugin when working with
|
||||||
|
eclipse. If you don’t already have m2eclipse installed it is available from the "eclipse
|
||||||
|
marketplace".</simpara>
|
||||||
|
<note>
|
||||||
|
<simpara>Older versions of m2e do not support Maven 3.3, so once the
|
||||||
|
projects are imported into Eclipse you will also need to tell
|
||||||
|
m2eclipse to use the right profile for the projects. If you
|
||||||
|
see many different errors related to the POMs in the projects, check
|
||||||
|
that you have an up to date installation. If you can’t upgrade m2e,
|
||||||
|
add the "spring" profile to your <literal>settings.xml</literal>. Alternatively you can
|
||||||
|
copy the repository settings from the "spring" profile of the parent
|
||||||
|
pom into your <literal>settings.xml</literal>.</simpara>
|
||||||
|
</note>
|
||||||
|
</section>
|
||||||
|
<section xml:id="_importing_into_eclipse_without_m2eclipse">
|
||||||
|
<title>Importing into eclipse without m2eclipse</title>
|
||||||
|
<simpara>If you prefer not to use m2eclipse you can generate eclipse project metadata using the
|
||||||
|
following command:</simpara>
|
||||||
|
<screen>$ ./mvnw eclipse:eclipse</screen>
|
||||||
|
<simpara>The generated eclipse projects can be imported by selecting <literal>import existing projects</literal>
|
||||||
|
from the <literal>file</literal> menu.</simpara>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
||||||
|
<chapter xml:id="_contributing">
|
||||||
|
<title>Contributing</title>
|
||||||
|
<simpara>Spring Cloud is released under the non-restrictive Apache 2.0 license,
|
||||||
|
and follows a very standard Github development process, using Github
|
||||||
|
tracker for issues and merging pull requests into master. If you want
|
||||||
|
to contribute even something trivial please do not hesitate, but
|
||||||
|
follow the guidelines below.</simpara>
|
||||||
|
<section xml:id="_sign_the_contributor_license_agreement">
|
||||||
|
<title>Sign the Contributor License Agreement</title>
|
||||||
|
<simpara>Before we accept a non-trivial patch or pull request we will need you to sign the
|
||||||
|
<link xl:href="https://cla.pivotal.io/sign/spring">Contributor License Agreement</link>.
|
||||||
|
Signing the contributor’s agreement does not grant anyone commit rights to the main
|
||||||
|
repository, but it does mean that we can accept your contributions, and you will get an
|
||||||
|
author credit if we do. Active contributors might be asked to join the core team, and
|
||||||
|
given the ability to merge pull requests.</simpara>
|
||||||
|
</section>
|
||||||
|
<section xml:id="_code_of_conduct">
|
||||||
|
<title>Code of Conduct</title>
|
||||||
|
<simpara>This project adheres to the Contributor Covenant <link xl:href="https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc">code of
|
||||||
|
conduct</link>. By participating, you are expected to uphold this code. Please report
|
||||||
|
unacceptable behavior to <link xl:href="mailto:spring-code-of-conduct@pivotal.io">spring-code-of-conduct@pivotal.io</link>.</simpara>
|
||||||
|
</section>
|
||||||
|
<section xml:id="_code_conventions_and_housekeeping">
|
||||||
|
<title>Code Conventions and Housekeeping</title>
|
||||||
|
<simpara>None of these is essential for a pull request, but they will all help. They can also be
|
||||||
|
added after the original pull request but before a merge.</simpara>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>Use the Spring Framework code format conventions. If you use Eclipse
|
||||||
|
you can import formatter settings using the
|
||||||
|
<literal>eclipse-code-formatter.xml</literal> file from the
|
||||||
|
<link xl:href="https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml">Spring
|
||||||
|
Cloud Build</link> project. If using IntelliJ, you can use the
|
||||||
|
<link xl:href="http://plugins.jetbrains.com/plugin/6546">Eclipse Code Formatter
|
||||||
|
Plugin</link> to import the same file.</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>Make sure all new <literal>.java</literal> files to have a simple Javadoc class comment with at least an
|
||||||
|
<literal>@author</literal> tag identifying you, and preferably at least a paragraph on what the class is
|
||||||
|
for.</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>Add the ASF license header comment to all new <literal>.java</literal> files (copy from existing files
|
||||||
|
in the project)</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>Add yourself as an <literal>@author</literal> to the .java files that you modify substantially (more
|
||||||
|
than cosmetic changes).</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>Add some Javadocs and, if you change the namespace, some XSD doc elements.</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>A few unit tests would help a lot as well — someone has to do it.</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>If no-one else is using your branch, please rebase it against the current master (or
|
||||||
|
other target branch in the main project).</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>When writing a commit message please follow <link xl:href="http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html">these conventions</link>,
|
||||||
|
if you are fixing an existing issue please add <literal>Fixes gh-XXXX</literal> at the end of the commit
|
||||||
|
message (where XXXX is the issue number).</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
||||||
|
</book>
|
||||||